diff --git a/.storybook/storybook.requires.js b/.storybook/storybook.requires.js index 63580a3634..8d59eded78 100644 --- a/.storybook/storybook.requires.js +++ b/.storybook/storybook.requires.js @@ -64,8 +64,6 @@ const getStories = () => { "./app/screens/authentication-screen/authentication-check-screen.stories.tsx": require("../app/screens/authentication-screen/authentication-check-screen.stories.tsx"), "./app/screens/authentication-screen/authentication-screen.stories.tsx": require("../app/screens/authentication-screen/authentication-screen.stories.tsx"), "./app/screens/authentication-screen/pin-screen.stories.tsx": require("../app/screens/authentication-screen/pin-screen.stories.tsx"), - "./app/screens/people-screen/contacts/contacts-detail.stories.tsx": require("../app/screens/people-screen/contacts/contacts-detail.stories.tsx"), - "./app/screens/people-screen/people.stories.tsx": require("../app/screens/people-screen/people.stories.tsx"), "./app/screens/conversion-flow/conversion-success-screen.stories.tsx": require("../app/screens/conversion-flow/conversion-success-screen.stories.tsx"), "./app/screens/earns-map-screen/earns-map-screen.stories.tsx": require("../app/screens/earns-map-screen/earns-map-screen.stories.tsx"), "./app/screens/earns-screen/earns-quiz.stories.tsx": require("../app/screens/earns-screen/earns-quiz.stories.tsx"), @@ -76,10 +74,13 @@ const getStories = () => { "./app/screens/email-registration-screen/email-registration-initiate.stories.tsx": require("../app/screens/email-registration-screen/email-registration-initiate.stories.tsx"), "./app/screens/email-registration-screen/email-registration-validate.stories.tsx": require("../app/screens/email-registration-screen/email-registration-validate.stories.tsx"), "./app/screens/error-screen/error-screen.stories.tsx": require("../app/screens/error-screen/error-screen.stories.tsx"), + "./app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx": require("../app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx"), "./app/screens/galoy-address-screen/address-screen.stories.tsx": require("../app/screens/galoy-address-screen/address-screen.stories.tsx"), "./app/screens/get-started-screen/device-account-fail-modal.stories.tsx": require("../app/screens/get-started-screen/device-account-fail-modal.stories.tsx"), "./app/screens/get-started-screen/get-started-screen.stories.tsx": require("../app/screens/get-started-screen/get-started-screen.stories.tsx"), "./app/screens/home-screen/home-screen.stories.tsx": require("../app/screens/home-screen/home-screen.stories.tsx"), + "./app/screens/people-screen/contacts/contacts-detail.stories.tsx": require("../app/screens/people-screen/contacts/contacts-detail.stories.tsx"), + "./app/screens/people-screen/people.stories.tsx": require("../app/screens/people-screen/people.stories.tsx"), "./app/screens/phone-auth-screen/phone-login-flow.stories.tsx": require("../app/screens/phone-auth-screen/phone-login-flow.stories.tsx"), "./app/screens/phone-auth-screen/phone-login-validation.stories.tsx": require("../app/screens/phone-auth-screen/phone-login-validation.stories.tsx"), "./app/screens/receive-bitcoin-screen/qr-view.stories.tsx": require("../app/screens/receive-bitcoin-screen/qr-view.stories.tsx"), diff --git a/.storybook/storybook.tsx b/.storybook/storybook.tsx index a5693f3785..b5fb8e2d94 100644 --- a/.storybook/storybook.tsx +++ b/.storybook/storybook.tsx @@ -20,7 +20,7 @@ RNBootSplash.hide({ fade: true }) const StorybookUI = getStorybookUI({ enableWebsockets: true, // for @storybook/react-native-server onDeviceUI: true, - initialSelection: { kind: "Get started screen", name: "Default" }, + initialSelection: { kind: "Full onboarding screen", name: "Default" }, shouldPersistSelection: false, }) diff --git a/android/app/build.gradle b/android/app/build.gradle index dc76e2edad..67cbafa16d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -103,6 +103,10 @@ android { versionCode 583 versionName "2.2.125" missingDimensionStrategy 'react-native-camera', 'general' // React native camera + + // onfido requirement + multiDexEnabled true + } splits { abi { @@ -147,6 +151,12 @@ android { } } } + + configurations.all { + resolutionStrategy { + force 'com.google.android.play:core-common:2.0.2' + } + } } dependencies { @@ -168,6 +178,15 @@ dependencies { } else { implementation jscFlavor } + + // https://github.com/KjellConnelly/react-native-rate/issues/117 + // https://chat.openai.com/c/ba241381-615e-48b1-baa3-ce3dbc7246b7 + implementation(project(":react-native-rate")) { + exclude group: 'com.google.android.play', module: 'core-common' + exclude group: 'com.google.android.play', module: 'review' + } + + implementation 'androidx.multidex:multidex:2.0.1' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/android/app/src/main/java/com/galoyapp/MainApplication.java b/android/app/src/main/java/com/galoyapp/MainApplication.java index 913717eac1..4c595e2a8e 100644 --- a/android/app/src/main/java/com/galoyapp/MainApplication.java +++ b/android/app/src/main/java/com/galoyapp/MainApplication.java @@ -10,7 +10,10 @@ import com.facebook.soloader.SoLoader; import java.util.List; -public class MainApplication extends Application implements ReactApplication { +import androidx.multidex.MultiDexApplication; + + +public class MainApplication extends MultiDexApplication implements ReactApplication { private final ReactNativeHost mReactNativeHost = new DefaultReactNativeHost(this) { diff --git a/android/build.gradle b/android/build.gradle index 3919e536dd..9061e73486 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,7 +21,7 @@ buildscript { classpath("com.android.tools.build:gradle:7.4.1") classpath("com.facebook.react:react-native-gradle-plugin") - classpath 'com.google.gms:google-services:4.3.14' // firebase + classpath 'com.google.gms:google-services:4.3.15' // firebase classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2' } } diff --git a/app/components/contact-support-button/contact-support-button.tsx b/app/components/contact-support-button/contact-support-button.tsx index 6d9c869d7d..2032b88b87 100644 --- a/app/components/contact-support-button/contact-support-button.tsx +++ b/app/components/contact-support-button/contact-support-button.tsx @@ -10,7 +10,7 @@ import { useAppConfig } from "@app/hooks" export const ContactSupportButton = ({ containerStyle, }: { - containerStyle: StyleProp + containerStyle?: StyleProp }) => { const [showContactSupport, setShowContactSupport] = useState(false) const { LL } = useI18nContext() diff --git a/app/components/notification/notification.tsx b/app/components/notification/notification.tsx index e2be9976e1..be52791c29 100644 --- a/app/components/notification/notification.tsx +++ b/app/components/notification/notification.tsx @@ -37,14 +37,13 @@ export const NotificationComponent = (): JSX.Element => { ) } - const notificationType = remoteMessage.data?.notificationType - if (notificationType) { - switch (true) { - case circlesNotificationTypes.includes(notificationType): - primaryNavigation.navigate("People") - setTimeout(() => circlesNavigation.navigate("circlesDashboard"), 200) - break - } + const notificationType = remoteMessage.data?.notificationType ?? "" + if ( + typeof notificationType === "string" && + circlesNotificationTypes.includes(notificationType) + ) { + primaryNavigation.navigate("People") + setTimeout(() => circlesNavigation.navigate("circlesDashboard"), 200) } } diff --git a/app/graphql/generated.gql b/app/graphql/generated.gql index b6c4fa6367..f884df85f2 100644 --- a/app/graphql/generated.gql +++ b/app/graphql/generated.gql @@ -455,6 +455,15 @@ mutation onChainUsdPaymentSendAsBtcDenominated($input: OnChainUsdPaymentSendAsBt } } +mutation onboardingFlowStart($input: OnboardingFlowStartInput!) { + onboardingFlowStart(input: $input) { + workflowRunId + tokenAndroid + tokenIos + __typename + } +} + mutation quizCompleted($input: QuizCompletedInput!) { quizCompleted(input: $input) { errors { @@ -960,6 +969,21 @@ query feedbackModalShown { feedbackModalShown @client } +query fullOnboardingScreen { + me { + id + defaultAccount { + ... on ConsumerAccount { + id + onboardingStatus + __typename + } + __typename + } + __typename + } +} + query hasPromptedSetDefaultAccount { hasPromptedSetDefaultAccount @client } diff --git a/app/graphql/generated.ts b/app/graphql/generated.ts index fc4aa11b63..ca838ee39f 100644 --- a/app/graphql/generated.ts +++ b/app/graphql/generated.ts @@ -301,6 +301,7 @@ export type ConsumerAccount = Account & { readonly level: AccountLevel; readonly limits: AccountLimits; readonly notificationSettings: NotificationSettings; + readonly onboardingStatus?: Maybe; /** List the quiz questions of the consumer account */ readonly quiz: ReadonlyArray; readonly realtimePrice: RealtimePrice; @@ -777,6 +778,7 @@ export type Mutation = { readonly onChainPaymentSendAll: PaymentSendPayload; readonly onChainUsdPaymentSend: PaymentSendPayload; readonly onChainUsdPaymentSendAsBtcDenominated: PaymentSendPayload; + readonly onboardingFlowStart: OnboardingFlowStartResult; readonly quizCompleted: QuizCompletedPayload; /** @deprecated will be moved to AccountContact */ readonly userContactUpdateAlias: UserContactUpdateAliasPayload; @@ -963,6 +965,11 @@ export type MutationOnChainUsdPaymentSendAsBtcDenominatedArgs = { }; +export type MutationOnboardingFlowStartArgs = { + input: OnboardingFlowStartInput; +}; + + export type MutationQuizCompletedArgs = { input: QuizCompletedInput; }; @@ -1129,6 +1136,30 @@ export type OnChainUsdTxFee = { readonly amount: Scalars['CentAmount']['output']; }; +export type OnboardingFlowStartInput = { + readonly firstName: Scalars['String']['input']; + readonly lastName: Scalars['String']['input']; +}; + +export type OnboardingFlowStartResult = { + readonly __typename: 'OnboardingFlowStartResult'; + readonly tokenAndroid: Scalars['String']['output']; + readonly tokenIos: Scalars['String']['output']; + readonly workflowRunId: Scalars['String']['output']; +}; + +export const OnboardingStatus = { + Abandoned: 'ABANDONED', + Approved: 'APPROVED', + AwaitingInput: 'AWAITING_INPUT', + Declined: 'DECLINED', + Error: 'ERROR', + NotStarted: 'NOT_STARTED', + Processing: 'PROCESSING', + Review: 'REVIEW' +} as const; + +export type OnboardingStatus = typeof OnboardingStatus[keyof typeof OnboardingStatus]; export type OneDayAccountLimit = AccountLimit & { readonly __typename: 'OneDayAccountLimit'; /** The rolling time interval value in seconds for the current 24 hour period. */ @@ -2010,6 +2041,18 @@ export type UserEmailRegistrationValidateMutationVariables = Exact<{ export type UserEmailRegistrationValidateMutation = { readonly __typename: 'Mutation', readonly userEmailRegistrationValidate: { readonly __typename: 'UserEmailRegistrationValidatePayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly me?: { readonly __typename: 'User', readonly id: string, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null } | null } }; +export type OnboardingFlowStartMutationVariables = Exact<{ + input: OnboardingFlowStartInput; +}>; + + +export type OnboardingFlowStartMutation = { readonly __typename: 'Mutation', readonly onboardingFlowStart: { readonly __typename: 'OnboardingFlowStartResult', readonly workflowRunId: string, readonly tokenAndroid: string, readonly tokenIos: string } }; + +export type FullOnboardingScreenQueryVariables = Exact<{ [key: string]: never; }>; + + +export type FullOnboardingScreenQuery = { readonly __typename: 'Query', readonly me?: { readonly __typename: 'User', readonly id: string, readonly defaultAccount: { readonly __typename: 'ConsumerAccount', readonly id: string, readonly onboardingStatus?: OnboardingStatus | null } } | null }; + export type AddressScreenQueryVariables = Exact<{ [key: string]: never; }>; @@ -3682,6 +3725,81 @@ export function useUserEmailRegistrationValidateMutation(baseOptions?: Apollo.Mu export type UserEmailRegistrationValidateMutationHookResult = ReturnType; export type UserEmailRegistrationValidateMutationResult = Apollo.MutationResult; export type UserEmailRegistrationValidateMutationOptions = Apollo.BaseMutationOptions; +export const OnboardingFlowStartDocument = gql` + mutation onboardingFlowStart($input: OnboardingFlowStartInput!) { + onboardingFlowStart(input: $input) { + workflowRunId + tokenAndroid + tokenIos + } +} + `; +export type OnboardingFlowStartMutationFn = Apollo.MutationFunction; + +/** + * __useOnboardingFlowStartMutation__ + * + * To run a mutation, you first call `useOnboardingFlowStartMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useOnboardingFlowStartMutation` 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 [onboardingFlowStartMutation, { data, loading, error }] = useOnboardingFlowStartMutation({ + * variables: { + * input: // value for 'input' + * }, + * }); + */ +export function useOnboardingFlowStartMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(OnboardingFlowStartDocument, options); + } +export type OnboardingFlowStartMutationHookResult = ReturnType; +export type OnboardingFlowStartMutationResult = Apollo.MutationResult; +export type OnboardingFlowStartMutationOptions = Apollo.BaseMutationOptions; +export const FullOnboardingScreenDocument = gql` + query fullOnboardingScreen { + me { + id + defaultAccount { + ... on ConsumerAccount { + id + onboardingStatus + } + } + } +} + `; + +/** + * __useFullOnboardingScreenQuery__ + * + * To run a query within a React component, call `useFullOnboardingScreenQuery` and pass it any options that fit your needs. + * When your component renders, `useFullOnboardingScreenQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFullOnboardingScreenQuery({ + * variables: { + * }, + * }); + */ +export function useFullOnboardingScreenQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FullOnboardingScreenDocument, options); + } +export function useFullOnboardingScreenLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FullOnboardingScreenDocument, options); + } +export type FullOnboardingScreenQueryHookResult = ReturnType; +export type FullOnboardingScreenLazyQueryHookResult = ReturnType; +export type FullOnboardingScreenQueryResult = Apollo.QueryResult; export const AddressScreenDocument = gql` query addressScreen { me { @@ -6751,6 +6869,9 @@ export type ResolversTypes = { OnChainUsdPaymentSendAsBtcDenominatedInput: OnChainUsdPaymentSendAsBtcDenominatedInput; OnChainUsdPaymentSendInput: OnChainUsdPaymentSendInput; OnChainUsdTxFee: ResolverTypeWrapper; + OnboardingFlowStartInput: OnboardingFlowStartInput; + OnboardingFlowStartResult: ResolverTypeWrapper; + OnboardingStatus: OnboardingStatus; OneDayAccountLimit: ResolverTypeWrapper; OneTimeAuthCode: ResolverTypeWrapper; PageInfo: ResolverTypeWrapper; @@ -6951,6 +7072,8 @@ export type ResolversParentTypes = { OnChainUsdPaymentSendAsBtcDenominatedInput: OnChainUsdPaymentSendAsBtcDenominatedInput; OnChainUsdPaymentSendInput: OnChainUsdPaymentSendInput; OnChainUsdTxFee: OnChainUsdTxFee; + OnboardingFlowStartInput: OnboardingFlowStartInput; + OnboardingFlowStartResult: OnboardingFlowStartResult; OneDayAccountLimit: OneDayAccountLimit; OneTimeAuthCode: Scalars['OneTimeAuthCode']['output']; PageInfo: PageInfo; @@ -7168,6 +7291,7 @@ export type ConsumerAccountResolvers; limits?: Resolver; notificationSettings?: Resolver; + onboardingStatus?: Resolver, ParentType, ContextType>; quiz?: Resolver, ParentType, ContextType>; realtimePrice?: Resolver; transactions?: Resolver, ParentType, ContextType, Partial>; @@ -7447,6 +7571,7 @@ export type MutationResolvers>; onChainUsdPaymentSend?: Resolver>; onChainUsdPaymentSendAsBtcDenominated?: Resolver>; + onboardingFlowStart?: Resolver>; quizCompleted?: Resolver>; userContactUpdateAlias?: Resolver>; userEmailDelete?: Resolver; @@ -7521,6 +7646,13 @@ export type OnChainUsdTxFeeResolvers; }; +export type OnboardingFlowStartResultResolvers = { + tokenAndroid?: Resolver; + tokenIos?: Resolver; + workflowRunId?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type OneDayAccountLimitResolvers = { interval?: Resolver, ParentType, ContextType>; remainingLimit?: Resolver, ParentType, ContextType>; @@ -8007,6 +8139,7 @@ export type Resolvers = { OnChainTxHash?: GraphQLScalarType; OnChainUpdate?: OnChainUpdateResolvers; OnChainUsdTxFee?: OnChainUsdTxFeeResolvers; + OnboardingFlowStartResult?: OnboardingFlowStartResultResolvers; OneDayAccountLimit?: OneDayAccountLimitResolvers; OneTimeAuthCode?: GraphQLScalarType; PageInfo?: PageInfoResolvers; diff --git a/app/i18n/en/index.ts b/app/i18n/en/index.ts index 88cb5ce28e..aadb333f29 100644 --- a/app/i18n/en/index.ts +++ b/app/i18n/en/index.ts @@ -2410,11 +2410,6 @@ const en: BaseTranslation = { stablesatTransfers: "Stablesat Transfers", internalSend: "Send to {bankName: string} User", error: "Unable to fetch limits at this time", - contactUsMessageBody: - "Hi, I will like to increase the transaction limits of my {bankName: string} account.", - contactUsMessageSubject: "Request To Increase Transaction Limits", - contactSupportToPerformKyc: - "Contact support to perform manual KYC to increase your limit", increaseLimits: "Increase your limits", }, TransactionScreen: { @@ -2764,8 +2759,25 @@ const en: BaseTranslation = { details: "We're giving away 1,000,000 sats!\n\n Share your Circles on social with tag `#blinkcircles` to enter! The winner will be chosen at random on October 31st.\n\n You must have at least one person in your Inner Circle to enter!", connectOnSocial: "Connect on social: ", fullDetails: "Full details at " - } + }, }, + FullOnboarding: { + title: "Full onboarding", + confirmNameTitle: "Name confirmation", + firstName: "First name", + lastName: "Last name", + confirmNameContent: "Is the spelling of your name correct?\n\n{firstName: string} {lastName: string}\n\nIt must match the name on your ID.", + requirements: "Upgrading your account will increase your limits and give you additional functionality such as transfer to bank accounts in selected countries.\n\nYou will have to provide your name, a governement issued ID and a selfie. We'll start with your name.", + success: "Documents has been successfully received and will be processed shortly. you can come back to this page to have an update on the status of your onboarding", + error: "There has been an error with the submission of your documents. You can contact the support is the problem persists.", + status: "Your onboarding status is: ", + ABANDONED: "Abandoned", + APPROVED: "Approved", + DECLINED: "Declined", + ERROR: "Error", + PROCESSING: "Processing", + REVIEW: "Review", + } } export default en diff --git a/app/i18n/i18n-types.ts b/app/i18n/i18n-types.ts index b46ee8226a..2c128b7bc1 100644 --- a/app/i18n/i18n-types.ts +++ b/app/i18n/i18n-types.ts @@ -7505,19 +7505,6 @@ type RootTranslation = { * U​n​a​b​l​e​ ​t​o​ ​f​e​t​c​h​ ​l​i​m​i​t​s​ ​a​t​ ​t​h​i​s​ ​t​i​m​e */ error: string - /** - * H​i​,​ ​I​ ​w​i​l​l​ ​l​i​k​e​ ​t​o​ ​i​n​c​r​e​a​s​e​ ​t​h​e​ ​t​r​a​n​s​a​c​t​i​o​n​ ​l​i​m​i​t​s​ ​o​f​ ​m​y​ ​{​b​a​n​k​N​a​m​e​}​ ​a​c​c​o​u​n​t​. - * @param {string} bankName - */ - contactUsMessageBody: RequiredParams<'bankName'> - /** - * R​e​q​u​e​s​t​ ​T​o​ ​I​n​c​r​e​a​s​e​ ​T​r​a​n​s​a​c​t​i​o​n​ ​L​i​m​i​t​s - */ - contactUsMessageSubject: string - /** - * C​o​n​t​a​c​t​ ​s​u​p​p​o​r​t​ ​t​o​ ​p​e​r​f​o​r​m​ ​m​a​n​u​a​l​ ​K​Y​C​ ​t​o​ ​i​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t - */ - contactSupportToPerformKyc: string /** * I​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​s */ @@ -8662,6 +8649,76 @@ type RootTranslation = { fullDetails: string } } + FullOnboarding: { + /** + * F​u​l​l​ ​o​n​b​o​a​r​d​i​n​g + */ + title: string + /** + * N​a​m​e​ ​c​o​n​f​i​r​m​a​t​i​o​n + */ + confirmNameTitle: string + /** + * F​i​r​s​t​ ​n​a​m​e + */ + firstName: string + /** + * L​a​s​t​ ​n​a​m​e + */ + lastName: string + /** + * I​s​ ​t​h​e​ ​s​p​e​l​l​i​n​g​ ​o​f​ ​y​o​u​r​ ​n​a​m​e​ ​c​o​r​r​e​c​t​?​ + ​ + ​{​f​i​r​s​t​N​a​m​e​}​ ​{​l​a​s​t​N​a​m​e​}​ + ​ + ​I​t​ ​m​u​s​t​ ​m​a​t​c​h​ ​t​h​e​ ​n​a​m​e​ ​o​n​ ​y​o​u​r​ ​I​D​. + * @param {string} firstName + * @param {string} lastName + */ + confirmNameContent: RequiredParams<'firstName' | 'lastName'> + /** + * U​p​g​r​a​d​i​n​g​ ​y​o​u​r​ ​a​c​c​o​u​n​t​ ​w​i​l​l​ ​i​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​s​ ​a​n​d​ ​g​i​v​e​ ​y​o​u​ ​a​d​d​i​t​i​o​n​a​l​ ​f​u​n​c​t​i​o​n​a​l​i​t​y​ ​s​u​c​h​ ​a​s​ ​t​r​a​n​s​f​e​r​ ​t​o​ ​b​a​n​k​ ​a​c​c​o​u​n​t​s​ ​i​n​ ​s​e​l​e​c​t​e​d​ ​c​o​u​n​t​r​i​e​s​.​ + ​ + ​Y​o​u​ ​w​i​l​l​ ​h​a​v​e​ ​t​o​ ​p​r​o​v​i​d​e​ ​y​o​u​r​ ​n​a​m​e​,​ ​a​ ​g​o​v​e​r​n​e​m​e​n​t​ ​i​s​s​u​e​d​ ​I​D​ ​a​n​d​ ​a​ ​s​e​l​f​i​e​.​ ​W​e​'​l​l​ ​s​t​a​r​t​ ​w​i​t​h​ ​y​o​u​r​ ​n​a​m​e​. + */ + requirements: string + /** + * D​o​c​u​m​e​n​t​s​ ​h​a​s​ ​b​e​e​n​ ​s​u​c​c​e​s​s​f​u​l​l​y​ ​r​e​c​e​i​v​e​d​ ​a​n​d​ ​w​i​l​l​ ​b​e​ ​p​r​o​c​e​s​s​e​d​ ​s​h​o​r​t​l​y​.​ ​y​o​u​ ​c​a​n​ ​c​o​m​e​ ​b​a​c​k​ ​t​o​ ​t​h​i​s​ ​p​a​g​e​ ​t​o​ ​h​a​v​e​ ​a​n​ ​u​p​d​a​t​e​ ​o​n​ ​t​h​e​ ​s​t​a​t​u​s​ ​o​f​ ​y​o​u​r​ ​o​n​b​o​a​r​d​i​n​g + */ + success: string + /** + * T​h​e​r​e​ ​h​a​s​ ​b​e​e​n​ ​a​n​ ​e​r​r​o​r​ ​w​i​t​h​ ​t​h​e​ ​s​u​b​m​i​s​s​i​o​n​ ​o​f​ ​y​o​u​r​ ​d​o​c​u​m​e​n​t​s​.​ ​Y​o​u​ ​c​a​n​ ​c​o​n​t​a​c​t​ ​t​h​e​ ​s​u​p​p​o​r​t​ ​i​s​ ​t​h​e​ ​p​r​o​b​l​e​m​ ​p​e​r​s​i​s​t​s​. + */ + error: string + /** + * Y​o​u​r​ ​o​n​b​o​a​r​d​i​n​g​ ​s​t​a​t​u​s​ ​i​s​:​ + */ + status: string + /** + * A​b​a​n​d​o​n​e​d + */ + ABANDONED: string + /** + * A​p​p​r​o​v​e​d + */ + APPROVED: string + /** + * D​e​c​l​i​n​e​d + */ + DECLINED: string + /** + * E​r​r​o​r + */ + ERROR: string + /** + * P​r​o​c​e​s​s​i​n​g + */ + PROCESSING: string + /** + * R​e​v​i​e​w + */ + REVIEW: string + } } export type TranslationFunctions = { @@ -16086,18 +16143,6 @@ export type TranslationFunctions = { * Unable to fetch limits at this time */ error: () => LocalizedString - /** - * Hi, I will like to increase the transaction limits of my {bankName} account. - */ - contactUsMessageBody: (arg: { bankName: string }) => LocalizedString - /** - * Request To Increase Transaction Limits - */ - contactUsMessageSubject: () => LocalizedString - /** - * Contact support to perform manual KYC to increase your limit - */ - contactSupportToPerformKyc: () => LocalizedString /** * Increase your limits */ @@ -17211,6 +17256,74 @@ export type TranslationFunctions = { fullDetails: () => LocalizedString } } + FullOnboarding: { + /** + * Full onboarding + */ + title: () => LocalizedString + /** + * Name confirmation + */ + confirmNameTitle: () => LocalizedString + /** + * First name + */ + firstName: () => LocalizedString + /** + * Last name + */ + lastName: () => LocalizedString + /** + * Is the spelling of your name correct? + + {firstName} {lastName} + + It must match the name on your ID. + */ + confirmNameContent: (arg: { firstName: string, lastName: string }) => LocalizedString + /** + * Upgrading your account will increase your limits and give you additional functionality such as transfer to bank accounts in selected countries. + + You will have to provide your name, a governement issued ID and a selfie. We'll start with your name. + */ + requirements: () => LocalizedString + /** + * Documents has been successfully received and will be processed shortly. you can come back to this page to have an update on the status of your onboarding + */ + success: () => LocalizedString + /** + * There has been an error with the submission of your documents. You can contact the support is the problem persists. + */ + error: () => LocalizedString + /** + * Your onboarding status is: + */ + status: () => LocalizedString + /** + * Abandoned + */ + ABANDONED: () => LocalizedString + /** + * Approved + */ + APPROVED: () => LocalizedString + /** + * Declined + */ + DECLINED: () => LocalizedString + /** + * Error + */ + ERROR: () => LocalizedString + /** + * Processing + */ + PROCESSING: () => LocalizedString + /** + * Review + */ + REVIEW: () => LocalizedString + } } export type Formatters = { diff --git a/app/i18n/raw-i18n/source/en.json b/app/i18n/raw-i18n/source/en.json index fc903d1da7..eb7b2aa977 100644 --- a/app/i18n/raw-i18n/source/en.json +++ b/app/i18n/raw-i18n/source/en.json @@ -2334,9 +2334,6 @@ "stablesatTransfers": "Stablesat Transfers", "internalSend": "Send to {bankName: string} User", "error": "Unable to fetch limits at this time", - "contactUsMessageBody": "Hi, I will like to increase the transaction limits of my {bankName: string} account.", - "contactUsMessageSubject": "Request To Increase Transaction Limits", - "contactSupportToPerformKyc": "Contact support to perform manual KYC to increase your limit", "increaseLimits": "Increase your limits" }, "TransactionScreen": { @@ -2655,5 +2652,22 @@ "connectOnSocial": "Connect on social: ", "fullDetails": "Full details at " } + }, + "FullOnboarding": { + "title": "Full onboarding", + "confirmNameTitle": "Name confirmation", + "firstName": "First name", + "lastName": "Last name", + "confirmNameContent": "Is the spelling of your name correct?\n\n{firstName: string} {lastName: string}\n\nIt must match the name on your ID.", + "requirements": "Upgrading your account will increase your limits and give you additional functionality such as transfer to bank accounts in selected countries.\n\nYou will have to provide your name, a governement issued ID and a selfie. We'll start with your name.", + "success": "Documents has been successfully received and will be processed shortly. you can come back to this page to have an update on the status of your onboarding", + "error": "There has been an error with the submission of your documents. You can contact the support is the problem persists.", + "status": "Your onboarding status is: ", + "ABANDONED": "Abandoned", + "APPROVED": "Approved", + "DECLINED": "Declined", + "ERROR": "Error", + "PROCESSING": "Processing", + "REVIEW": "Review" } } diff --git a/app/navigation/root-navigator.tsx b/app/navigation/root-navigator.tsx index b43d45ef95..4dd0d8dbb0 100644 --- a/app/navigation/root-navigator.tsx +++ b/app/navigation/root-navigator.tsx @@ -80,6 +80,7 @@ import { RootStackParamList, } from "./stack-param-lists" import { NotificationSettingsScreen } from "@app/screens/settings-screen/notifications-screen" +import { FullOnboardingFlowScreen } from "@app/screens/full-onboarding-flow" const RootNavigator = createStackNavigator() @@ -403,6 +404,13 @@ export const RootStack = () => { title: "WebView", // should be overridden by the navigate action with an initial title }} /> + ) } diff --git a/app/navigation/stack-param-lists.ts b/app/navigation/stack-param-lists.ts index 1ee85549b7..398b99a78a 100644 --- a/app/navigation/stack-param-lists.ts +++ b/app/navigation/stack-param-lists.ts @@ -91,6 +91,7 @@ export type RootStackParamList = { totpRegistrationValidate: { totpRegistrationId: string } totpLoginValidate: { authToken: string } webView: { url: string; initialTitle?: string } + fullOnboardingFlow: undefined } export type PeopleStackParamList = { diff --git a/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx b/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx new file mode 100644 index 0000000000..25082b2563 --- /dev/null +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx @@ -0,0 +1,66 @@ +import * as React from "react" +import { StoryScreen } from "../../../.storybook/views" +import { MockedProvider } from "@apollo/client/testing" +import { createCache } from "../../graphql/cache" +import { FullOnboardingFlowScreen } from "./full-onboarding-flow" +import { FullOnboardingScreenDocument } from "../../graphql/generated" + +export default { + title: "Full onboarding screen", + component: FullOnboardingFlowScreen, + decorators: [(Story) => {Story()}], +} + +const notStarted = [ + { + request: { + query: FullOnboardingScreenDocument, + }, + result: { + data: { + me: { + id: "id", + defaultAccount: { + id: "id", + onboardingStatus: "NOT_STARTED", + __typename: "ConsumerAccount", + }, + __typename: "User", + }, + }, + }, + }, +] + +const approved = [ + { + request: { + query: FullOnboardingScreenDocument, + }, + result: { + data: { + me: { + id: "id", + defaultAccount: { + id: "id", + onboardingStatus: "APPROVED", + __typename: "ConsumerAccount", + }, + __typename: "User", + }, + }, + }, + }, +] + +export const Default = () => ( + + + +) + +export const Approved = () => ( + + + +) diff --git a/app/screens/full-onboarding-flow/full-onboarding-flow.tsx b/app/screens/full-onboarding-flow/full-onboarding-flow.tsx new file mode 100644 index 0000000000..d02be9ac4e --- /dev/null +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.tsx @@ -0,0 +1,233 @@ +import { gql } from "@apollo/client" +import { GaloyPrimaryButton } from "@app/components/atomic/galoy-primary-button" +import { ContactSupportButton } from "@app/components/contact-support-button/contact-support-button" +import { Screen } from "@app/components/screen" +import { + OnboardingStatus, + useFullOnboardingScreenQuery, + useOnboardingFlowStartMutation, +} from "@app/graphql/generated" +import { useI18nContext } from "@app/i18n/i18n-react" +import { isIos } from "@app/utils/helper" +import Onfido, { OnfidoTheme } from "@onfido/react-native-sdk" +import { useNavigation } from "@react-navigation/native" +import { Input, Text, makeStyles, useTheme } from "@rneui/themed" +import React, { useEffect, useState } from "react" +import { ActivityIndicator, Alert, View } from "react-native" + +gql` + mutation onboardingFlowStart($input: OnboardingFlowStartInput!) { + onboardingFlowStart(input: $input) { + workflowRunId + tokenAndroid + tokenIos + } + } + + query fullOnboardingScreen { + me { + id + defaultAccount { + ... on ConsumerAccount { + id + onboardingStatus + } + } + } + } +` + +export const FullOnboardingFlowScreen: React.FC = () => { + const navigation = useNavigation() + + const { LL } = useI18nContext() + + const { + theme: { colors }, + } = useTheme() + + const styles = useStyles() + + const { data, loading } = useFullOnboardingScreenQuery({ fetchPolicy: "network-only" }) + + const onboardingStatus = data?.me?.defaultAccount?.onboardingStatus + + const [onboardingFlowStart] = useOnboardingFlowStartMutation() + + const [firstName, setFirstName] = useState("") + const [lastName, setLastName] = useState("") + + const confirmNames = async () => { + Alert.alert( + LL.FullOnboarding.confirmNameTitle(), + LL.FullOnboarding.confirmNameContent({ firstName, lastName }), + [ + { text: LL.common.cancel(), onPress: () => {} }, + { + text: LL.common.yes(), + onPress: onfidoStart, + }, + ], + ) + } + + const onfidoStart = React.useCallback(async () => { + const res = await onboardingFlowStart({ + variables: { input: { firstName, lastName } }, + }) + + const workflowRunId = res.data?.onboardingFlowStart?.workflowRunId + if (!workflowRunId) { + Alert.alert("no workflowRunId") + return + } + + const tokenAndroid = res.data?.onboardingFlowStart?.tokenAndroid + const tokenIos = res.data?.onboardingFlowStart?.tokenIos + + const sdkToken = isIos ? tokenIos : tokenAndroid + + if (!sdkToken) { + Alert.alert("no sdkToken") + return + } + + try { + /* eslint @typescript-eslint/ban-ts-comment: "off" */ + // @ts-expect-error + await Onfido.start({ + sdkToken, + theme: OnfidoTheme.AUTOMATIC, + workflowRunId, + }) + + Alert.alert(LL.common.success(), LL.FullOnboarding.success(), [ + { + text: LL.common.ok(), + onPress: () => { + navigation.goBack() + }, + }, + ]) + } catch (err) { + console.error(err, "error") + let message = "" + if (err instanceof Error) { + message = err.message + } + + if (message.match(/canceled/i)) { + navigation.goBack() + return + } + + Alert.alert( + LL.FullOnboarding.error(), + `${LL.GaloyAddressScreen.somethingWentWrong()}\n\n${message}`, + [ + { + text: LL.common.ok(), + onPress: () => { + navigation.goBack() + }, + }, + ], + ) + } + }, [LL, firstName, lastName, navigation, onboardingFlowStart]) + + useEffect(() => { + if (onboardingStatus === OnboardingStatus.AwaitingInput) { + onfidoStart() + } + }, [onboardingStatus, onfidoStart]) + + if (loading) { + return ( + + + + + + ) + } + + if ( + onboardingStatus === OnboardingStatus.Abandoned || + onboardingStatus === OnboardingStatus.Approved || + onboardingStatus === OnboardingStatus.Declined || + onboardingStatus === OnboardingStatus.Error || + onboardingStatus === OnboardingStatus.Processing || + onboardingStatus === OnboardingStatus.Review + ) { + return ( + + {`${LL.FullOnboarding.status()}${LL.FullOnboarding[onboardingStatus]()}.`} + + + ) + } + + return ( + + + {LL.FullOnboarding.requirements()} + + <> + setFirstName(text)} + /> + setLastName(text)} + /> + + + + + + ) +} + +const useStyles = makeStyles(() => ({ + screenStyle: { + padding: 20, + flexGrow: 1, + }, + + textStyle: { + marginBottom: 32, + }, + + buttonContainer: { + flex: 1, + justifyContent: "flex-end", + }, + + verticalAlignment: { flex: 1, justifyContent: "center", alignItems: "center" }, +})) diff --git a/app/screens/full-onboarding-flow/index.ts b/app/screens/full-onboarding-flow/index.ts new file mode 100644 index 0000000000..6d3c7412f2 --- /dev/null +++ b/app/screens/full-onboarding-flow/index.ts @@ -0,0 +1 @@ +export * from "./full-onboarding-flow" diff --git a/app/screens/send-bitcoin-screen/send-bitcoin-details-extra-info.tsx b/app/screens/send-bitcoin-screen/send-bitcoin-details-extra-info.tsx index 221841b37f..a5cb15be07 100644 --- a/app/screens/send-bitcoin-screen/send-bitcoin-details-extra-info.tsx +++ b/app/screens/send-bitcoin-screen/send-bitcoin-details-extra-info.tsx @@ -6,9 +6,11 @@ import { Text, makeStyles } from "@rneui/themed" import { AccountLevel } from "@app/graphql/level-context" import { useI18nContext } from "@app/i18n/i18n-react" import { useDisplayCurrency } from "@app/hooks/use-display-currency" + +import { GaloyPrimaryButton } from "@app/components/atomic/galoy-primary-button" import { useNavigation } from "@react-navigation/native" -import { RootStackParamList } from "@app/navigation/stack-param-lists" import { StackNavigationProp } from "@react-navigation/stack" +import { RootStackParamList } from "@app/navigation/stack-param-lists" export type SendBitcoinDetailsExtraInfoProps = { errorMessage?: string @@ -21,17 +23,14 @@ export const SendBitcoinDetailsExtraInfo = ({ amountStatus, currentLevel, }: SendBitcoinDetailsExtraInfoProps) => { + const navigation = useNavigation>() + const [isUpgradeAccountModalVisible, setIsUpgradeAccountModalVisible] = useState(false) const closeModal = () => setIsUpgradeAccountModalVisible(false) const openModal = () => setIsUpgradeAccountModalVisible(true) const { LL } = useI18nContext() const { formatMoneyAmount } = useDisplayCurrency() const styles = useStyles() - const navigation = useNavigation>() - - const navigateToTransactionLimits = () => { - navigation.navigate("transactionLimitsScreen") - } if (errorMessage) { return @@ -62,13 +61,10 @@ export const SendBitcoinDetailsExtraInfo = ({ ) : null} {currentLevel === "ONE" ? ( - - {LL.TransactionLimitsScreen.contactSupportToPerformKyc()} - + navigation.navigate("fullOnboardingFlow")} + /> ) : null} ) diff --git a/app/screens/settings-screen/account-screen.tsx b/app/screens/settings-screen/account-screen.tsx index d5b7fe57f6..8d51b6b653 100644 --- a/app/screens/settings-screen/account-screen.tsx +++ b/app/screens/settings-screen/account-screen.tsx @@ -143,7 +143,7 @@ export const AccountScreen = () => { const openUpgradeAccountModal = () => setUpgradeAccountModalVisible(true) const { data } = useAccountScreenQuery({ - fetchPolicy: "cache-first", + fetchPolicy: "cache-and-network", skip: !isAtLeastLevelZero, }) @@ -437,6 +437,15 @@ export const AccountScreen = () => { styleDivider: true, }, + { + category: LL.AccountScreen.upgrade(), + id: "upgrade-to-level-two", + icon: "person-outline", + action: () => navigation.navigate("fullOnboardingFlow"), + enabled: true, + hidden: currentLevel !== AccountLevel.One, + styleDivider: true, + }, { category: LL.common.backupAccount(), id: "upgrade-to-level-one", diff --git a/app/screens/settings-screen/transaction-limits-screen.tsx b/app/screens/settings-screen/transaction-limits-screen.tsx index cba801fd95..87cd0444c0 100644 --- a/app/screens/settings-screen/transaction-limits-screen.tsx +++ b/app/screens/settings-screen/transaction-limits-screen.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ActivityIndicator, Button, Pressable, View } from "react-native" +import { ActivityIndicator, Button, View } from "react-native" import { LocalizedString } from "typesafe-i18n" import { Screen } from "@app/components/screen" @@ -11,13 +11,12 @@ import { useDisplayCurrency } from "@app/hooks/use-display-currency" import { useAppConfig, usePriceConversion } from "@app/hooks" import { DisplayCurrency, toUsdMoneyAmount } from "@app/types/amounts" import { makeStyles, Text, useTheme } from "@rneui/themed" -import ContactModal, { - SupportChannels, -} from "@app/components/contact-modal/contact-modal" -import { GaloyIcon } from "@app/components/atomic/galoy-icon" import { UpgradeAccountModal } from "@app/components/upgrade-account-modal" import { AccountLevel, useLevel } from "@app/graphql/level-context" import { GaloyPrimaryButton } from "@app/components/atomic/galoy-primary-button" +import { useNavigation } from "@react-navigation/native" +import { StackNavigationProp } from "@react-navigation/stack" +import { RootStackParamList } from "@app/navigation/stack-param-lists" const useStyles = makeStyles(({ colors }) => ({ limitWrapper: { @@ -26,7 +25,7 @@ const useStyles = makeStyles(({ colors }) => ({ }, increaseLimitsButtonContainer: { marginVertical: 20, - paddingHorizontal: 20, + marginHorizontal: 20, }, contentTextBox: { flexDirection: "row", @@ -119,6 +118,8 @@ gql` ` export const TransactionLimitsScreen = () => { + const navigation = useNavigation>() + const styles = useStyles() const { theme: { colors }, @@ -134,23 +135,13 @@ export const TransactionLimitsScreen = () => { const { name: bankName } = appConfig.galoyInstance const { currentLevel } = useLevel() - const [isContactModalVisible, setIsContactModalVisible] = React.useState(false) const [isUpgradeAccountModalVisible, setIsUpgradeAccountModalVisible] = React.useState(false) - const toggleIsContactModalVisible = () => { - setIsContactModalVisible(!isContactModalVisible) - } - const toggleIsUpgradeAccountModalVisible = () => { setIsUpgradeAccountModalVisible(!isUpgradeAccountModalVisible) } - const messageBody = LL.TransactionLimitsScreen.contactUsMessageBody({ - bankName, - }) - const messageSubject = LL.TransactionLimitsScreen.contactUsMessageSubject() - if (error) { return ( @@ -226,31 +217,21 @@ export const TransactionLimitsScreen = () => { ))} - {currentLevel === AccountLevel.Zero ? ( + {currentLevel === AccountLevel.Zero && ( navigation.navigate("phoneFlow")} + containerStyle={styles.increaseLimitsButtonContainer} + /> + )} + {currentLevel === AccountLevel.One && ( + navigation.navigate("fullOnboardingFlow")} containerStyle={styles.increaseLimitsButtonContainer} /> - ) : ( - - - {LL.TransactionLimitsScreen.contactSupportToPerformKyc()} - - - )} - 10.7.0) - - Firebase/AppCheck (10.7.0): + - FirebaseAnalytics/WithoutAdIdSupport (~> 10.15.0) + - Firebase/AppCheck (10.15.0): - Firebase/CoreOnly - - FirebaseAppCheck (~> 10.7.0) - - Firebase/CoreOnly (10.7.0): - - FirebaseCore (= 10.7.0) - - Firebase/Crashlytics (10.7.0): + - FirebaseAppCheck (~> 10.15.0) + - Firebase/CoreOnly (10.15.0): + - FirebaseCore (= 10.15.0) + - Firebase/Crashlytics (10.15.0): - Firebase/CoreOnly - - FirebaseCrashlytics (~> 10.7.0) - - Firebase/Messaging (10.7.0): + - FirebaseCrashlytics (~> 10.15.0) + - Firebase/Messaging (10.15.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 10.7.0) - - Firebase/RemoteConfig (10.7.0): + - FirebaseMessaging (~> 10.15.0) + - Firebase/RemoteConfig (10.15.0): - Firebase/CoreOnly - - FirebaseRemoteConfig (~> 10.7.0) - - FirebaseABTesting (10.9.0): + - FirebaseRemoteConfig (~> 10.15.0) + - FirebaseABTesting (10.16.0): - FirebaseCore (~> 10.0) - - FirebaseAnalytics/WithoutAdIdSupport (10.7.0): + - FirebaseAnalytics/WithoutAdIdSupport (10.15.0): - FirebaseCore (~> 10.0) - FirebaseInstallations (~> 10.0) - - GoogleAppMeasurement/WithoutAdIdSupport (= 10.7.0) - - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - - GoogleUtilities/MethodSwizzler (~> 7.8) - - GoogleUtilities/Network (~> 7.8) - - "GoogleUtilities/NSData+zlib (~> 7.8)" + - GoogleAppMeasurement/WithoutAdIdSupport (= 10.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.11) + - GoogleUtilities/MethodSwizzler (~> 7.11) + - GoogleUtilities/Network (~> 7.11) + - "GoogleUtilities/NSData+zlib (~> 7.11)" - nanopb (< 2.30910.0, >= 2.30908.0) - - FirebaseAppCheck (10.7.0): + - FirebaseAppCheck (10.15.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - PromisesObjC (~> 2.1) - - FirebaseCore (10.7.0): + - FirebaseCore (10.15.0): - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Logger (~> 7.8) - - FirebaseCoreExtension (10.7.0): + - FirebaseCoreExtension (10.15.0): - FirebaseCore (~> 10.0) - - FirebaseCoreInternal (10.9.0): + - FirebaseCoreInternal (10.16.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - - FirebaseCrashlytics (10.7.0): + - FirebaseCrashlytics (10.15.0): - FirebaseCore (~> 10.5) - FirebaseInstallations (~> 10.0) - FirebaseSessions (~> 10.5) @@ -59,12 +59,12 @@ PODS: - GoogleUtilities/Environment (~> 7.8) - nanopb (< 2.30910.0, >= 2.30908.0) - PromisesObjC (~> 2.1) - - FirebaseInstallations (10.9.0): + - FirebaseInstallations (10.16.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - PromisesObjC (~> 2.1) - - FirebaseMessaging (10.7.0): + - FirebaseMessaging (10.15.0): - FirebaseCore (~> 10.0) - FirebaseInstallations (~> 10.0) - GoogleDataTransport (~> 9.2) @@ -73,13 +73,13 @@ PODS: - GoogleUtilities/Reachability (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - nanopb (< 2.30910.0, >= 2.30908.0) - - FirebaseRemoteConfig (10.7.0): + - FirebaseRemoteConfig (10.15.0): - FirebaseABTesting (~> 10.0) - FirebaseCore (~> 10.0) - FirebaseInstallations (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - "GoogleUtilities/NSData+zlib (~> 7.8)" - - FirebaseSessions (10.9.0): + - FirebaseSessions (10.16.0): - FirebaseCore (~> 10.5) - FirebaseCoreExtension (~> 10.0) - FirebaseInstallations (~> 10.0) @@ -89,13 +89,13 @@ PODS: - PromisesSwift (~> 2.1) - fmt (6.2.1) - glog (0.3.5) - - GoogleAppMeasurement/WithoutAdIdSupport (10.7.0): - - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - - GoogleUtilities/MethodSwizzler (~> 7.8) - - GoogleUtilities/Network (~> 7.8) - - "GoogleUtilities/NSData+zlib (~> 7.8)" + - GoogleAppMeasurement/WithoutAdIdSupport (10.15.0): + - GoogleUtilities/AppDelegateSwizzler (~> 7.11) + - GoogleUtilities/MethodSwizzler (~> 7.11) + - GoogleUtilities/Network (~> 7.11) + - "GoogleUtilities/NSData+zlib (~> 7.11)" - nanopb (< 2.30910.0, >= 2.30908.0) - - GoogleDataTransport (9.2.3): + - GoogleDataTransport (9.2.5): - GoogleUtilities/Environment (~> 7.7) - nanopb (< 2.30910.0, >= 2.30908.0) - PromisesObjC (< 3.0, >= 1.2) @@ -116,28 +116,28 @@ PODS: - GoogleToolboxForMac/Defines (= 2.3.2) - "GoogleToolboxForMac/NSString+URLArguments (= 2.3.2)" - "GoogleToolboxForMac/NSString+URLArguments (2.3.2)" - - GoogleUtilities/AppDelegateSwizzler (7.11.1): + - GoogleUtilities/AppDelegateSwizzler (7.11.5): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (7.11.1): + - GoogleUtilities/Environment (7.11.5): - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.11.1): + - GoogleUtilities/Logger (7.11.5): - GoogleUtilities/Environment - - GoogleUtilities/MethodSwizzler (7.11.1): + - GoogleUtilities/MethodSwizzler (7.11.5): - GoogleUtilities/Logger - - GoogleUtilities/Network (7.11.1): + - GoogleUtilities/Network (7.11.5): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.11.1)" - - GoogleUtilities/Reachability (7.11.1): + - "GoogleUtilities/NSData+zlib (7.11.5)" + - GoogleUtilities/Reachability (7.11.5): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (7.11.1): + - GoogleUtilities/UserDefaults (7.11.5): - GoogleUtilities/Logger - GoogleUtilitiesComponents (1.1.0): - GoogleUtilities/Logger - - GT3Captcha-iOS (0.15.8.1) + - GT3Captcha-iOS (0.15.8.3) - GTMSessionFetcher/Core (2.3.0) - hermes-engine (0.71.8): - hermes-engine/Pre-built (= 0.71.8) @@ -166,9 +166,13 @@ PODS: - nanopb/encode (= 2.30909.0) - nanopb/decode (2.30909.0) - nanopb/encode (2.30909.0) - - PromisesObjC (2.2.0) - - PromisesSwift (2.2.0): - - PromisesObjC (= 2.2.0) + - Onfido (29.5.1) + - onfido-react-native-sdk (10.4.0): + - Onfido (~> 29.5.0) + - React + - PromisesObjC (2.3.1) + - PromisesSwift (2.3.1): + - PromisesObjC (= 2.3.1) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -543,29 +547,29 @@ PODS: - React-Core - RNDeviceInfo (10.6.0): - React-Core - - RNFBAnalytics (17.4.2): - - Firebase/AnalyticsWithoutAdIdSupport (= 10.7.0) + - RNFBAnalytics (18.5.0): + - Firebase/AnalyticsWithoutAdIdSupport (= 10.15.0) - React-Core - RNFBApp - - RNFBApp (17.4.3): - - Firebase/CoreOnly (= 10.7.0) + - RNFBApp (18.5.0): + - Firebase/CoreOnly (= 10.15.0) - React-Core - - RNFBAppCheck (17.4.2): - - Firebase/AppCheck (= 10.7.0) + - RNFBAppCheck (18.5.0): + - Firebase/AppCheck (= 10.15.0) - React-Core - RNFBApp - - RNFBCrashlytics (17.5.0): - - Firebase/Crashlytics (= 10.7.0) - - FirebaseCoreExtension (= 10.7.0) + - RNFBCrashlytics (18.5.0): + - Firebase/Crashlytics (= 10.15.0) + - FirebaseCoreExtension (= 10.15.0) - React-Core - RNFBApp - - RNFBMessaging (17.4.2): - - Firebase/Messaging (= 10.7.0) - - FirebaseCoreExtension (= 10.7.0) + - RNFBMessaging (18.5.0): + - Firebase/Messaging (= 10.15.0) + - FirebaseCoreExtension (= 10.15.0) - React-Core - RNFBApp - - RNFBRemoteConfig (17.4.3): - - Firebase/RemoteConfig (= 10.7.0) + - RNFBRemoteConfig (18.5.0): + - Firebase/RemoteConfig (= 10.15.0) - React-Core - RNFBApp - RNGestureHandler (2.9.0): @@ -629,9 +633,9 @@ PODS: - React-callinvoker - React-Core - Yoga (1.14.0) - - ZXingObjC (3.6.5): - - ZXingObjC/All (= 3.6.5) - - ZXingObjC/All (3.6.5) + - ZXingObjC (3.6.9): + - ZXingObjC/All (= 3.6.9) + - ZXingObjC/All (3.6.9) DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) @@ -642,6 +646,7 @@ DEPENDENCIES: - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - libevent (~> 2.1.12) + - "onfido-react-native-sdk (from `../node_modules/@onfido/react-native-sdk`)" - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) @@ -738,6 +743,7 @@ SPEC REPOS: - MLKitCommon - MLKitVision - nanopb + - Onfido - PromisesObjC - PromisesSwift - ZXingObjC @@ -757,6 +763,8 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + onfido-react-native-sdk: + :path: "../node_modules/@onfido/react-native-sdk" RCT-Folly: :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" RCTRequired: @@ -894,27 +902,27 @@ SPEC CHECKSUMS: DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: f637f31eacba90d4fdeff3fa41608b8f361c173b FBReactNativeSpec: 0d9a4f4de7ab614c49e98c00aedfd3bfbda33d59 - Firebase: 0219acf760880eeec8ce479895bd7767466d9f81 - FirebaseABTesting: 005b70969e2817e2a1e631e8dba29134a04c0622 - FirebaseAnalytics: f8133442ee6f8512e28ff19e62ce15398bfaeace - FirebaseAppCheck: 81143f6f973d277962b71e16c63068a8f4a755dc - FirebaseCore: e317665b9d744727a97e623edbbed009320afdd7 - FirebaseCoreExtension: f17247ba8c61e4d3c8d136b5e2de3cb4ac6a85b6 - FirebaseCoreInternal: d2b4acb827908e72eca47a9fd896767c3053921e - FirebaseCrashlytics: 35fdd1a433b31e28adcf5c8933f4c526691a1e0b - FirebaseInstallations: c58489c9caacdbf27d1da60891a87318e20218e0 - FirebaseMessaging: ac9062bcc35ed56e15a0241d8fd317022499baf8 - FirebaseRemoteConfig: d5de62211e2eaa2152d8ee85a23c301b70887a74 - FirebaseSessions: 44a6782502eb279a214d4adca20891353278760c + Firebase: 66043bd4579e5b73811f96829c694c7af8d67435 + FirebaseABTesting: 03f0a8b88cf618350527f2c6a2234e29b9c65064 + FirebaseAnalytics: 47cef43728f81a839cf1306576bdd77ffa2eac7e + FirebaseAppCheck: 66eea1c882cddd1bce9d92a0a7efd596f7204782 + FirebaseCore: 2cec518b43635f96afe7ac3a9c513e47558abd2e + FirebaseCoreExtension: d3f1ea3725fb41f56e8fbfb29eeaff54e7ffb8f6 + FirebaseCoreInternal: 26233f705cc4531236818a07ac84d20c333e505a + FirebaseCrashlytics: a83f26fb922a3fe181eb738fb4dcf0c92bba6455 + FirebaseInstallations: b822f91a61f7d1ba763e5ccc9d4f2e6f2ed3b3ee + FirebaseMessaging: 0c0ae1eb722ef0c07f7801e5ded8dccd1357d6d4 + FirebaseRemoteConfig: 64b6ada098c649304114a817effd7e5f87229b11 + FirebaseSessions: 96e7781e545929cde06dd91088ddbb0841391b43 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - GoogleAppMeasurement: fe17c92a32207dd5cdd4e8d742767f2da74857f6 - GoogleDataTransport: f0308f5905a745f94fb91fea9c6cbaf3831cb1bd + GoogleAppMeasurement: 722db6550d1e6d552b08398b69a975ac61039338 + GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2 GoogleMLKit: 2bd0dc6253c4d4f227aad460f69215a504b2980e GoogleToolboxForMac: 8bef7c7c5cf7291c687cf5354f39f9db6399ad34 - GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749 + GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084 GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe - GT3Captcha-iOS: d9cdc6fcd8eac43d374eacf7079a2c420a25cafc + GT3Captcha-iOS: 5e3b1077834d8a9d6f4d64a447a30af3e14affe6 GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2 hermes-engine: 47986d26692ae75ee7a17ab049caee8864f855de libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 @@ -923,8 +931,10 @@ SPEC CHECKSUMS: MLKitCommon: c1b791c3e667091918d91bda4bba69a91011e390 MLKitVision: 8baa5f46ee3352614169b85250574fde38c36f49 nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 - PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef - PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959 + Onfido: 9f2d7e79ee300783a0359a902accf1b6e10e8c26 + onfido-react-native-sdk: 62867f1949c559dec9cb235eae09ca039528a0af + PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 + PromisesSwift: 28dca69a9c40779916ac2d6985a0192a5cb4a265 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: 8af6a32dfc2b65ec82193c2dee6e1011ff22ac2a RCTTypeSafety: bee9dd161c175896c680d47ef1d9eaacf2b587f4 @@ -968,12 +978,12 @@ SPEC CHECKSUMS: RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc RNDateTimePicker: 65e1d202799460b286ff5e741d8baf54695e8abd RNDeviceInfo: 475a4c447168d0ad4c807e48ef5e0963a0f4eb1b - RNFBAnalytics: ded9b8059b53b55d054ecb308931427281e39d8b - RNFBApp: e8a35f0ef545dfa1be1f09411ea2078f870a9089 - RNFBAppCheck: ce3dff9967762aadf092397b04fa1084ae9affbb - RNFBCrashlytics: cd370021582bf4ba67cf0af1aa11955c59d4c6b7 - RNFBMessaging: 5d1480ff1fa7fd8dfd5a1a7f0df35c709f75dd4e - RNFBRemoteConfig: f888b638ab942ff923b5fa11e24cfbb02a858d21 + RNFBAnalytics: cc406ee9bd0ddaad8d14400586cec215660bbf4c + RNFBApp: cc9384746945ac0eedd4759171a8abb4c4c5309d + RNFBAppCheck: 6e213103efa8b8cef25151dffafd85b95d6eca0b + RNFBCrashlytics: e691d843de6074360e9afaf6b475ee285fb65b56 + RNFBMessaging: 3c573398dced30f6cbaf55a195080916ea23f819 + RNFBRemoteConfig: 3b872da757ed617b83d4a780d7bd0915cc82bd03 RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 RNInAppBrowser: e36d6935517101ccba0e875bac8ad7b0cb655364 RNKeychain: ff836453cba46938e0e9e4c22e43d43fa2c90333 @@ -990,8 +1000,8 @@ SPEC CHECKSUMS: vision-camera-code-scanner: dda884a7f3ec8243a2a6d6489b91860648371bca VisionCamera: 523b49054bee9dace64189ab6631cb41e8b83fe0 Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 - ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb + ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5 PODFILE CHECKSUM: bb6529ab88d2e95007f12b67f3974e0e60c964a6 -COCOAPODS: 1.12.1 +COCOAPODS: 1.13.0 diff --git a/package.json b/package.json index 4797fe8c7e..ebfeee89ee 100644 --- a/package.json +++ b/package.json @@ -60,14 +60,15 @@ "@formatjs/intl-relativetimeformat": "^11.2.3", "@galoymoney/client": "^0.2.5", "@galoymoney/react-native-geetest-module": "^0.1.3", + "@onfido/react-native-sdk": "^10.4.0", "@react-native-async-storage/async-storage": "^1.19.3", "@react-native-clipboard/clipboard": "^1.11.1", - "@react-native-firebase/analytics": "17", - "@react-native-firebase/app": "^17.4.3", - "@react-native-firebase/app-check": "^17.4.2", - "@react-native-firebase/crashlytics": "17", - "@react-native-firebase/messaging": "17", - "@react-native-firebase/remote-config": "^17.4.3", + "@react-native-firebase/analytics": "^18.5.0", + "@react-native-firebase/app": "^18.5.0", + "@react-native-firebase/app-check": "^18.5.0", + "@react-native-firebase/crashlytics": "^18.5.0", + "@react-native-firebase/messaging": "^18.5.0", + "@react-native-firebase/remote-config": "^18.5.0", "@react-navigation/bottom-tabs": "^6.5.4", "@react-navigation/native": "^6.1.3", "@react-navigation/stack": "^6.3.12", diff --git a/supergraph-config.yaml b/supergraph-config.yaml index cd796f65be..a270e06c7d 100644 --- a/supergraph-config.yaml +++ b/supergraph-config.yaml @@ -3,8 +3,12 @@ subgraphs: galoy: routing_url: url schema: - file: ../galoy/dev/apollo-federation/supergraph.graphql + file: ../galoy/core/api/dev/apollo-federation/supergraph.graphql circles: routing_url: url schema: file: ../blink-circles/src/graphql/schema.graphql + kyc: + routing_url: url + schema: + file: ../blink-kyc/app/graphql/schema.graphql diff --git a/supergraph.graphql b/supergraph.graphql index 6096dfb1de..17948af9f8 100644 --- a/supergraph.graphql +++ b/supergraph.graphql @@ -290,6 +290,7 @@ type ConsumerAccount implements Account @join__implements(graph: GALOY, interface: "Account") @join__type(graph: CIRCLES, key: "id") @join__type(graph: GALOY) + @join__type(graph: KYC, key: "id") { id: ID! welcomeProfile: WelcomeProfile @join__field(graph: CIRCLES) @@ -327,6 +328,7 @@ type ConsumerAccount implements Account walletIds: [WalletId] ): TransactionConnection @join__field(graph: GALOY) wallets: [Wallet!]! @join__field(graph: GALOY) + onboardingStatus: OnboardingStatus @join__field(graph: KYC) } """ @@ -560,6 +562,7 @@ scalar join__FieldSet enum join__Graph { CIRCLES @join__graph(name: "circles", url: "url") GALOY @join__graph(name: "galoy", url: "url") + KYC @join__graph(name: "kyc", url: "url") } scalar Language @@ -796,6 +799,25 @@ type LnUpdate walletId: WalletId! } +input LnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipientInput + @join__type(graph: GALOY) +{ + """Amount in satoshis.""" + amount: SatAmount! + descriptionHash: Hex32Bytes + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """ + Optional memo for the lightning invoice. Acts as a note to the recipient. + """ + memo: Memo + + """Wallet ID for a USD wallet which belongs to the account of any user.""" + recipientWalletId: WalletId! +} + input LnUsdInvoiceCreateInput @join__type(graph: GALOY) { @@ -870,86 +892,95 @@ type MobileVersions type Mutation @join__type(graph: GALOY) + @join__type(graph: KYC) { - accountDelete: AccountDeletePayload! - accountDisableNotificationCategory(input: AccountDisableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! - accountDisableNotificationChannel(input: AccountDisableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! - accountEnableNotificationCategory(input: AccountEnableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! - accountEnableNotificationChannel(input: AccountEnableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! - accountUpdateDefaultWalletId(input: AccountUpdateDefaultWalletIdInput!): AccountUpdateDefaultWalletIdPayload! - accountUpdateDisplayCurrency(input: AccountUpdateDisplayCurrencyInput!): AccountUpdateDisplayCurrencyPayload! - callbackEndpointAdd(input: CallbackEndpointAddInput!): CallbackEndpointAddPayload! - callbackEndpointDelete(input: CallbackEndpointDeleteInput!): SuccessPayload! - captchaCreateChallenge: CaptchaCreateChallengePayload! - captchaRequestAuthCode(input: CaptchaRequestAuthCodeInput!): SuccessPayload! - deviceNotificationTokenCreate(input: DeviceNotificationTokenCreateInput!): SuccessPayload! - feedbackSubmit(input: FeedbackSubmitInput!): SuccessPayload! + accountDelete: AccountDeletePayload! @join__field(graph: GALOY) + accountDisableNotificationCategory(input: AccountDisableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: GALOY) + accountDisableNotificationChannel(input: AccountDisableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: GALOY) + accountEnableNotificationCategory(input: AccountEnableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: GALOY) + accountEnableNotificationChannel(input: AccountEnableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: GALOY) + accountUpdateDefaultWalletId(input: AccountUpdateDefaultWalletIdInput!): AccountUpdateDefaultWalletIdPayload! @join__field(graph: GALOY) + accountUpdateDisplayCurrency(input: AccountUpdateDisplayCurrencyInput!): AccountUpdateDisplayCurrencyPayload! @join__field(graph: GALOY) + callbackEndpointAdd(input: CallbackEndpointAddInput!): CallbackEndpointAddPayload! @join__field(graph: GALOY) + callbackEndpointDelete(input: CallbackEndpointDeleteInput!): SuccessPayload! @join__field(graph: GALOY) + captchaCreateChallenge: CaptchaCreateChallengePayload! @join__field(graph: GALOY) + captchaRequestAuthCode(input: CaptchaRequestAuthCodeInput!): SuccessPayload! @join__field(graph: GALOY) + deviceNotificationTokenCreate(input: DeviceNotificationTokenCreateInput!): SuccessPayload! @join__field(graph: GALOY) + feedbackSubmit(input: FeedbackSubmitInput!): SuccessPayload! @join__field(graph: GALOY) """ Actions a payment which is internal to the ledger e.g. it does not use onchain/lightning. Returns payment status (success, failed, pending, already_paid). """ - intraLedgerPaymentSend(input: IntraLedgerPaymentSendInput!): PaymentSendPayload! + intraLedgerPaymentSend(input: IntraLedgerPaymentSendInput!): PaymentSendPayload! @join__field(graph: GALOY) """ Actions a payment which is internal to the ledger e.g. it does not use onchain/lightning. Returns payment status (success, failed, pending, already_paid). """ - intraLedgerUsdPaymentSend(input: IntraLedgerUsdPaymentSendInput!): PaymentSendPayload! + intraLedgerUsdPaymentSend(input: IntraLedgerUsdPaymentSendInput!): PaymentSendPayload! @join__field(graph: GALOY) """ Returns a lightning invoice for an associated wallet. When invoice is paid the value will be credited to a BTC wallet. Expires after 'expiresIn' or 24 hours. """ - lnInvoiceCreate(input: LnInvoiceCreateInput!): LnInvoicePayload! + lnInvoiceCreate(input: LnInvoiceCreateInput!): LnInvoicePayload! @join__field(graph: GALOY) """ Returns a lightning invoice for an associated wallet. When invoice is paid the value will be credited to a BTC wallet. Expires after 'expiresIn' or 24 hours. """ - lnInvoiceCreateOnBehalfOfRecipient(input: LnInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! - lnInvoiceFeeProbe(input: LnInvoiceFeeProbeInput!): SatAmountPayload! + lnInvoiceCreateOnBehalfOfRecipient(input: LnInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! @join__field(graph: GALOY) + lnInvoiceFeeProbe(input: LnInvoiceFeeProbeInput!): SatAmountPayload! @join__field(graph: GALOY) """ Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. Provided wallet can be USD or BTC and must have sufficient balance to cover amount in lightning invoice. Returns payment status (success, failed, pending, already_paid). """ - lnInvoicePaymentSend(input: LnInvoicePaymentInput!): PaymentSendPayload! + lnInvoicePaymentSend(input: LnInvoicePaymentInput!): PaymentSendPayload! @join__field(graph: GALOY) """ Returns a lightning invoice for an associated wallet. Can be used to receive any supported currency value (currently USD or BTC). Expires after 'expiresIn' or 24 hours for BTC invoices or 5 minutes for USD invoices. """ - lnNoAmountInvoiceCreate(input: LnNoAmountInvoiceCreateInput!): LnNoAmountInvoicePayload! + lnNoAmountInvoiceCreate(input: LnNoAmountInvoiceCreateInput!): LnNoAmountInvoicePayload! @join__field(graph: GALOY) """ Returns a lightning invoice for an associated wallet. Can be used to receive any supported currency value (currently USD or BTC). Expires after 'expiresIn' or 24 hours for BTC invoices or 5 minutes for USD invoices. """ - lnNoAmountInvoiceCreateOnBehalfOfRecipient(input: LnNoAmountInvoiceCreateOnBehalfOfRecipientInput!): LnNoAmountInvoicePayload! - lnNoAmountInvoiceFeeProbe(input: LnNoAmountInvoiceFeeProbeInput!): SatAmountPayload! + lnNoAmountInvoiceCreateOnBehalfOfRecipient(input: LnNoAmountInvoiceCreateOnBehalfOfRecipientInput!): LnNoAmountInvoicePayload! @join__field(graph: GALOY) + lnNoAmountInvoiceFeeProbe(input: LnNoAmountInvoiceFeeProbeInput!): SatAmountPayload! @join__field(graph: GALOY) """ Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. Provided wallet must be BTC and must have sufficient balance to cover amount specified in mutation request. Returns payment status (success, failed, pending, already_paid). """ - lnNoAmountInvoicePaymentSend(input: LnNoAmountInvoicePaymentInput!): PaymentSendPayload! - lnNoAmountUsdInvoiceFeeProbe(input: LnNoAmountUsdInvoiceFeeProbeInput!): CentAmountPayload! + lnNoAmountInvoicePaymentSend(input: LnNoAmountInvoicePaymentInput!): PaymentSendPayload! @join__field(graph: GALOY) + lnNoAmountUsdInvoiceFeeProbe(input: LnNoAmountUsdInvoiceFeeProbeInput!): CentAmountPayload! @join__field(graph: GALOY) """ Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. Provided wallet must be USD and have sufficient balance to cover amount specified in mutation request. Returns payment status (success, failed, pending, already_paid). """ - lnNoAmountUsdInvoicePaymentSend(input: LnNoAmountUsdInvoicePaymentInput!): PaymentSendPayload! + lnNoAmountUsdInvoicePaymentSend(input: LnNoAmountUsdInvoicePaymentInput!): PaymentSendPayload! @join__field(graph: GALOY) + + """ + Returns a lightning invoice denominated in satoshis for an associated wallet. + When invoice is paid the equivalent value at invoice creation will be credited to a USD wallet. + Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate + associated with the amount). + """ + lnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipient(input: LnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipientInput!): LnInvoicePayload! @join__field(graph: GALOY) """ Returns a lightning invoice denominated in satoshis for an associated wallet. @@ -957,7 +988,7 @@ type Mutation Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate associated with the amount). """ - lnUsdInvoiceCreate(input: LnUsdInvoiceCreateInput!): LnInvoicePayload! + lnUsdInvoiceCreate(input: LnUsdInvoiceCreateInput!): LnInvoicePayload! @join__field(graph: GALOY) """ Returns a lightning invoice denominated in satoshis for an associated wallet. @@ -965,31 +996,31 @@ type Mutation Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate associated with the amount). """ - lnUsdInvoiceCreateOnBehalfOfRecipient(input: LnUsdInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! - lnUsdInvoiceFeeProbe(input: LnUsdInvoiceFeeProbeInput!): SatAmountPayload! - onChainAddressCreate(input: OnChainAddressCreateInput!): OnChainAddressPayload! - onChainAddressCurrent(input: OnChainAddressCurrentInput!): OnChainAddressPayload! - onChainPaymentSend(input: OnChainPaymentSendInput!): PaymentSendPayload! - onChainPaymentSendAll(input: OnChainPaymentSendAllInput!): PaymentSendPayload! - onChainUsdPaymentSend(input: OnChainUsdPaymentSendInput!): PaymentSendPayload! - onChainUsdPaymentSendAsBtcDenominated(input: OnChainUsdPaymentSendAsBtcDenominatedInput!): PaymentSendPayload! - quizCompleted(input: QuizCompletedInput!): QuizCompletedPayload! - userContactUpdateAlias(input: UserContactUpdateAliasInput!): UserContactUpdateAliasPayload! @deprecated(reason: "will be moved to AccountContact") - userEmailDelete: UserEmailDeletePayload! - userEmailRegistrationInitiate(input: UserEmailRegistrationInitiateInput!): UserEmailRegistrationInitiatePayload! - userEmailRegistrationValidate(input: UserEmailRegistrationValidateInput!): UserEmailRegistrationValidatePayload! - userLogin(input: UserLoginInput!): AuthTokenPayload! - userLoginUpgrade(input: UserLoginUpgradeInput!): UpgradePayload! - userLogout(input: UserLogoutInput): SuccessPayload! - userPhoneDelete: UserPhoneDeletePayload! - userPhoneRegistrationInitiate(input: UserPhoneRegistrationInitiateInput!): SuccessPayload! - userPhoneRegistrationValidate(input: UserPhoneRegistrationValidateInput!): UserPhoneRegistrationValidatePayload! - userQuizQuestionUpdateCompleted(input: UserQuizQuestionUpdateCompletedInput!): UserQuizQuestionUpdateCompletedPayload! @deprecated(reason: "Use QuizCompletedMutation instead") - userTotpDelete(input: UserTotpDeleteInput!): UserTotpDeletePayload! - userTotpRegistrationInitiate(input: UserTotpRegistrationInitiateInput!): UserTotpRegistrationInitiatePayload! - userTotpRegistrationValidate(input: UserTotpRegistrationValidateInput!): UserTotpRegistrationValidatePayload! - userUpdateLanguage(input: UserUpdateLanguageInput!): UserUpdateLanguagePayload! - userUpdateUsername(input: UserUpdateUsernameInput!): UserUpdateUsernamePayload! @deprecated(reason: "Username will be moved to @Handle in Accounts. Also SetUsername naming should be used instead of UpdateUsername to reflect the idempotency of Handles") + lnUsdInvoiceCreateOnBehalfOfRecipient(input: LnUsdInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! @join__field(graph: GALOY) + lnUsdInvoiceFeeProbe(input: LnUsdInvoiceFeeProbeInput!): SatAmountPayload! @join__field(graph: GALOY) + onChainAddressCreate(input: OnChainAddressCreateInput!): OnChainAddressPayload! @join__field(graph: GALOY) + onChainAddressCurrent(input: OnChainAddressCurrentInput!): OnChainAddressPayload! @join__field(graph: GALOY) + onChainPaymentSend(input: OnChainPaymentSendInput!): PaymentSendPayload! @join__field(graph: GALOY) + onChainPaymentSendAll(input: OnChainPaymentSendAllInput!): PaymentSendPayload! @join__field(graph: GALOY) + onChainUsdPaymentSend(input: OnChainUsdPaymentSendInput!): PaymentSendPayload! @join__field(graph: GALOY) + onChainUsdPaymentSendAsBtcDenominated(input: OnChainUsdPaymentSendAsBtcDenominatedInput!): PaymentSendPayload! @join__field(graph: GALOY) + quizCompleted(input: QuizCompletedInput!): QuizCompletedPayload! @join__field(graph: GALOY) + userContactUpdateAlias(input: UserContactUpdateAliasInput!): UserContactUpdateAliasPayload! @join__field(graph: GALOY) @deprecated(reason: "will be moved to AccountContact") + userEmailDelete: UserEmailDeletePayload! @join__field(graph: GALOY) + userEmailRegistrationInitiate(input: UserEmailRegistrationInitiateInput!): UserEmailRegistrationInitiatePayload! @join__field(graph: GALOY) + userEmailRegistrationValidate(input: UserEmailRegistrationValidateInput!): UserEmailRegistrationValidatePayload! @join__field(graph: GALOY) + userLogin(input: UserLoginInput!): AuthTokenPayload! @join__field(graph: GALOY) + userLoginUpgrade(input: UserLoginUpgradeInput!): UpgradePayload! @join__field(graph: GALOY) + userLogout(input: UserLogoutInput): SuccessPayload! @join__field(graph: GALOY) + userPhoneDelete: UserPhoneDeletePayload! @join__field(graph: GALOY) + userPhoneRegistrationInitiate(input: UserPhoneRegistrationInitiateInput!): SuccessPayload! @join__field(graph: GALOY) + userPhoneRegistrationValidate(input: UserPhoneRegistrationValidateInput!): UserPhoneRegistrationValidatePayload! @join__field(graph: GALOY) + userTotpDelete(input: UserTotpDeleteInput!): UserTotpDeletePayload! @join__field(graph: GALOY) + userTotpRegistrationInitiate(input: UserTotpRegistrationInitiateInput!): UserTotpRegistrationInitiatePayload! @join__field(graph: GALOY) + userTotpRegistrationValidate(input: UserTotpRegistrationValidateInput!): UserTotpRegistrationValidatePayload! @join__field(graph: GALOY) + userUpdateLanguage(input: UserUpdateLanguageInput!): UserUpdateLanguagePayload! @join__field(graph: GALOY) + userUpdateUsername(input: UserUpdateUsernameInput!): UserUpdateUsernamePayload! @join__field(graph: GALOY) @deprecated(reason: "Username will be moved to @Handle in Accounts. Also SetUsername naming should be used instead of UpdateUsername to reflect the idempotency of Handles") + onboardingFlowStart(input: OnboardingFlowStartInput!): OnboardingFlowStartResult! @join__field(graph: KYC) } type MyUpdatesPayload @@ -1031,6 +1062,34 @@ type NotificationSettings push: NotificationChannelSettings! } +input OnboardingFlowStartInput + @join__type(graph: KYC) +{ + firstName: String! + lastName: String! +} + +type OnboardingFlowStartResult + @join__type(graph: KYC) +{ + workflowRunId: String! + tokenAndroid: String! + tokenIos: String! +} + +enum OnboardingStatus + @join__type(graph: KYC) +{ + NOT_STARTED @join__enumValue(graph: KYC) + AWAITING_INPUT @join__enumValue(graph: KYC) + PROCESSING @join__enumValue(graph: KYC) + ABANDONED @join__enumValue(graph: KYC) + ERROR @join__enumValue(graph: KYC) + APPROVED @join__enumValue(graph: KYC) + REVIEW @join__enumValue(graph: KYC) + DECLINED @join__enumValue(graph: KYC) +} + """An address for an on-chain bitcoin destination""" scalar OnChainAddress @join__type(graph: GALOY) @@ -1299,10 +1358,10 @@ type PublicWallet type Query @join__type(graph: CIRCLES) @join__type(graph: GALOY) + @join__type(graph: KYC) { welcomeLeaderboard(input: WelcomeLeaderboardInput!): Leaderboard! @join__field(graph: CIRCLES) accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: GALOY) - btcPrice(currency: DisplayCurrency! = "USD"): Price @join__field(graph: GALOY) @deprecated(reason: "Deprecated in favor of realtimePrice") btcPriceList(range: PriceGraphRange!): [PricePoint] @join__field(graph: GALOY) businessMapMarkers: [MapMarker] @join__field(graph: GALOY) currencyList: [Currency!]! @join__field(graph: GALOY) @@ -1791,19 +1850,6 @@ type UserQuizQuestion question: QuizQuestion! } -input UserQuizQuestionUpdateCompletedInput - @join__type(graph: GALOY) -{ - id: ID! -} - -type UserQuizQuestionUpdateCompletedPayload - @join__type(graph: GALOY) -{ - errors: [Error!]! - userQuizQuestion: UserQuizQuestion -} - input UserTotpDeleteInput @join__type(graph: GALOY) { diff --git a/yarn.lock b/yarn.lock index a07454a1fd..4681a88ad7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3952,6 +3952,13 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@onfido/react-native-sdk@^10.4.0": + version "10.4.0" + resolved "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-10.4.0.tgz#e0cd780f457ae72c54a15f73ea0e76a551b0b437" + integrity sha512-bOKxhpepTizfNoJsv/vtEXQS/W9xT8BtC7ahC7lXC0U2nNNihUUk3yxoJFb7aVqD2in5D4DFnh8Uk57NnAfOFg== + dependencies: + js-base64 "3.7.5" + "@peculiar/asn1-schema@^2.1.6", "@peculiar/asn1-schema@^2.3.0": version "2.3.3" resolved "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz#21418e1f3819e0b353ceff0c2dad8ccb61acd777" @@ -4235,40 +4242,40 @@ resolved "https://registry.npmjs.org/@react-native-community/slider/-/slider-4.4.2.tgz#1fea0eb3ae31841fe87bd6c4fc67569066e9cf4b" integrity sha512-D9bv+3Vd2gairAhnRPAghwccgEmoM7g562pm8i4qB3Esrms5mggF81G3UvCyc0w3jjtFHh8dpQkfEoKiP0NW/Q== -"@react-native-firebase/analytics@17": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@react-native-firebase/analytics/-/analytics-17.4.2.tgz#f1d2e6e7dcb7152ef29962d5bbcb653194a6385f" - integrity sha512-hWidKfex0Yv/1cJ+WPQ/UMwSoSFnehEn3CQBhFTSKXdo8OrIymCpv74/9q3IWpvBRICCtgbRF8ZpqITJv6TCmA== +"@react-native-firebase/analytics@^18.5.0": + version "18.5.0" + resolved "https://registry.npmjs.org/@react-native-firebase/analytics/-/analytics-18.5.0.tgz#cca5858e44f3f8cbf387fa7cd6debb95fbcf8023" + integrity sha512-+8fkDedcftieOBEkNdqEW0lS/FB9SKzfUc3yYXnJcLTy3Ceg9JZga/tWz4BGbbxPddUy1Sm2UuWDuOxsdkFUyA== -"@react-native-firebase/app-check@^17.4.2": - version "17.4.2" - resolved "https://registry.npmjs.org/@react-native-firebase/app-check/-/app-check-17.4.2.tgz#d4985f344081278f711940e62c33af441af39264" - integrity sha512-YLUWpidrUMonniSbW7E1E8hQzqHO+Cd7X71QbdxsZ1AMfXKCfpgzrlVlicTvwWiAM/mCYqHUO1jX7rBC0WWIOw== +"@react-native-firebase/app-check@^18.5.0": + version "18.5.0" + resolved "https://registry.npmjs.org/@react-native-firebase/app-check/-/app-check-18.5.0.tgz#a0a20c1fb2ad5c76aee699d4e40b64f4c7812b6b" + integrity sha512-CUy9Ix2yrh3zxK3Dgcq6ZETLebMqcDC82iQJ4MkFiG9j6Ga1kTNl1VRDuirdiRSiwtu+XhRHHSD3X6esTEjPvQ== -"@react-native-firebase/app@^17.4.3": - version "17.4.3" - resolved "https://registry.yarnpkg.com/@react-native-firebase/app/-/app-17.4.3.tgz#50ea42f50bc9d4fec8a60633c163cbdb008ca52c" - integrity sha512-D+Cez5HrUmDzYcQxzYH8cM2ZENYaz4daTRshVqJEEQWeUerYdRAy8M6JAhP/wjQlSHkeDWnrJ1nVzBgeLFSyYQ== +"@react-native-firebase/app@^18.5.0": + version "18.5.0" + resolved "https://registry.npmjs.org/@react-native-firebase/app/-/app-18.5.0.tgz#198a133229d1b8710f257e76d9703dcb7e4cd6e0" + integrity sha512-AhHQi5KFDlKZn/lH7rEYtLfpsGamEq+P/cXZWcNPcP0WGlmi++abk7Pxnn4MjnG7TNhEyG/C9uq//qb6VhXaZg== dependencies: opencollective-postinstall "^2.0.1" superstruct "^0.6.2" -"@react-native-firebase/crashlytics@17": - version "17.5.0" - resolved "https://registry.yarnpkg.com/@react-native-firebase/crashlytics/-/crashlytics-17.5.0.tgz#0685e262b99f67150b268f60a739e0a051fb2245" - integrity sha512-BknqnrsGceKDT1jm+gArIymXLguPw1AKkAKqEyH/XU+K0Np6M7+VsISipHjO2dizyGlkFjIN2lGdqTvfLzRC9Q== +"@react-native-firebase/crashlytics@^18.5.0": + version "18.5.0" + resolved "https://registry.npmjs.org/@react-native-firebase/crashlytics/-/crashlytics-18.5.0.tgz#b5c1e15d260d5243c5ffb2963114bb7e42fe2b7f" + integrity sha512-i/jt/kNyhLws10/DeYgSQbGIekNPCAdtdg36NmFSw7URZf+1JUczKePbHqq3TvMFZJi5OjnDj06Fj9oenQKjWA== dependencies: stacktrace-js "^2.0.0" -"@react-native-firebase/messaging@17": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@react-native-firebase/messaging/-/messaging-17.4.2.tgz#ebc589bd0e77783f4b4330d71287fd150f9dc120" - integrity sha512-WgqDFjx4JfCed459jrFtzYcejIoBbQKBKGM5lSjmH/cIGU+5Kp9g0x5QNrXdZL5dNo91bW+jJB/6JMjOLH56fw== +"@react-native-firebase/messaging@^18.5.0": + version "18.5.0" + resolved "https://registry.npmjs.org/@react-native-firebase/messaging/-/messaging-18.5.0.tgz#2a80b25816470e9843682e031a3a113566067ce6" + integrity sha512-y1FApYxBMcygmbWBqUPFC+fCfvx6Yf6TdZewun7kPwx+S+tkYzoKx1IsXtxOXtqyJjCNEYirjFgNrs5SSd02zA== -"@react-native-firebase/remote-config@^17.4.3": - version "17.4.3" - resolved "https://registry.yarnpkg.com/@react-native-firebase/remote-config/-/remote-config-17.4.3.tgz#04fa98c77a565e82ed0ff72b5cf4b09b49ea30f6" - integrity sha512-fls5vMhN8xteSaiWzRwxZE01n+MJZihsmVG6eD70yNkEGjtHtyO1EddMKBX5pSNB9SfZy89kaKC7bz7uuD0xzw== +"@react-native-firebase/remote-config@^18.5.0": + version "18.5.0" + resolved "https://registry.npmjs.org/@react-native-firebase/remote-config/-/remote-config-18.5.0.tgz#5ece65cdd2b2c2179b6be409287f3b837ef39824" + integrity sha512-EOXToa1tLtskWjCAjW9RZHB19BHk8+MiLLS4B2DSAHs/t6QVRtjlK+xqI2nSppHSFdzMI6Nd9wi869baK/y5RA== "@react-native/assets@1.0.0": version "1.0.0" @@ -15453,6 +15460,11 @@ jpeg-js@^0.4.1, jpeg-js@^0.4.4: resolved "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== +js-base64@3.7.5: + version "3.7.5" + resolved "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + js-library-detector@^6.4.0: version "6.6.0" resolved "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.6.0.tgz#b531a4784f8242d87f68f6f3eafc771a0650fb9d"