From 574c686623f3d072f23d788005c185a74abaf523 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Mon, 25 Sep 2023 12:38:13 +0100 Subject: [PATCH 1/5] chore: test onfido --- .storybook/storybook.requires.js | 5 +- .storybook/storybook.tsx | 2 +- android/app/build.gradle | 6 + .../java/com/galoyapp/MainApplication.java | 5 +- app/graphql/generated.gql | 9 + app/graphql/generated.ts | 176 +++++++++++++++++- app/i18n/en/index.ts | 19 +- app/i18n/i18n-types.ts | 119 +++++++++--- app/i18n/raw-i18n/source/en.json | 17 +- app/navigation/root-navigator.tsx | 8 + app/navigation/stack-param-lists.ts | 1 + .../full-onboarding-flow.stories.tsx | 20 ++ .../full-onboarding-flow.tsx | 168 +++++++++++++++++ app/screens/full-onboarding-flow/index.ts | 1 + .../send-bitcoin-details-extra-info.tsx | 22 +-- .../transaction-limits-screen.tsx | 49 ++--- codegen.yml | 4 +- ios/GaloyApp.xcodeproj/project.pbxproj | 2 + ios/Podfile.lock | 14 +- package.json | 1 + supergraph-config.yaml | 6 +- supergraph.graphql | 150 ++++++++++----- yarn.lock | 12 ++ 23 files changed, 669 insertions(+), 147 deletions(-) create mode 100644 app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx create mode 100644 app/screens/full-onboarding-flow/full-onboarding-flow.tsx create mode 100644 app/screens/full-onboarding-flow/index.ts 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..53fc908c36 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 { @@ -168,6 +172,8 @@ dependencies { } else { implementation jscFlavor } + + 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/app/graphql/generated.gql b/app/graphql/generated.gql index b6c4fa6367..15bb802716 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 { diff --git a/app/graphql/generated.ts b/app/graphql/generated.ts index fc4aa11b63..f12675c5d9 100644 --- a/app/graphql/generated.ts +++ b/app/graphql/generated.ts @@ -82,6 +82,8 @@ export type Scalars = { Username: { input: string; output: string; } /** Unique identifier of a wallet */ WalletId: { input: string; output: string; } + join__FieldSet: { input: string; output: string; } + link__Import: { input: string; output: string; } _FieldSet: { input: string; output: string; } }; @@ -777,6 +779,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 +966,11 @@ export type MutationOnChainUsdPaymentSendAsBtcDenominatedArgs = { }; +export type MutationOnboardingFlowStartArgs = { + input: OnboardingFlowStartInput; +}; + + export type MutationQuizCompletedArgs = { input: QuizCompletedInput; }; @@ -1129,6 +1137,19 @@ export type OnChainUsdTxFee = { readonly amount: Scalars['CentAmount']['output']; }; +export type OnboardingFlowStartInput = { + readonly accountId: Scalars['String']['input']; + 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 type OneDayAccountLimit = AccountLimit & { readonly __typename: 'OneDayAccountLimit'; /** The rolling time interval value in seconds for the current 24 hour period. */ @@ -1269,6 +1290,7 @@ export type Query = { readonly feedbackModalShown: Scalars['Boolean']['output']; readonly globals?: Maybe; readonly hasPromptedSetDefaultAccount: Scalars['Boolean']['output']; + readonly hello?: Maybe; readonly hiddenBalanceToolTip: Scalars['Boolean']['output']; readonly hideBalance: Scalars['Boolean']['output']; readonly innerCircleValue: Scalars['Int']['output']; @@ -1839,6 +1861,21 @@ export const WelcomeRange = { } as const; export type WelcomeRange = typeof WelcomeRange[keyof typeof WelcomeRange]; +export const Join__Graph = { + Circles: 'CIRCLES', + Galoy: 'GALOY', + Kyc: 'KYC' +} as const; + +export type Join__Graph = typeof Join__Graph[keyof typeof Join__Graph]; +export const Link__Purpose = { + /** `EXECUTION` features provide metadata necessary for operation execution. */ + Execution: 'EXECUTION', + /** `SECURITY` features provide metadata necessary to securely resolve fields. */ + Security: 'SECURITY' +} as const; + +export type Link__Purpose = typeof Link__Purpose[keyof typeof Link__Purpose]; export type MobileUpdateQueryVariables = Exact<{ [key: string]: never; }>; @@ -2010,6 +2047,13 @@ 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 AddressScreenQueryVariables = Exact<{ [key: string]: never; }>; @@ -3682,6 +3726,41 @@ 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 AddressScreenDocument = gql` query addressScreen { me { @@ -6751,6 +6830,8 @@ export type ResolversTypes = { OnChainUsdPaymentSendAsBtcDenominatedInput: OnChainUsdPaymentSendAsBtcDenominatedInput; OnChainUsdPaymentSendInput: OnChainUsdPaymentSendInput; OnChainUsdTxFee: ResolverTypeWrapper; + OnboardingFlowStartInput: OnboardingFlowStartInput; + OnboardingFlowStartResult: ResolverTypeWrapper; OneDayAccountLimit: ResolverTypeWrapper; OneTimeAuthCode: ResolverTypeWrapper; PageInfo: ResolverTypeWrapper; @@ -6837,6 +6918,10 @@ export type ResolversTypes = { WelcomeLeaderboardInput: WelcomeLeaderboardInput; WelcomeProfile: ResolverTypeWrapper; WelcomeRange: WelcomeRange; + join__FieldSet: ResolverTypeWrapper; + join__Graph: Join__Graph; + link__Import: ResolverTypeWrapper; + link__Purpose: Link__Purpose; }; /** Mapping between all available schema types and the resolvers parents */ @@ -6951,6 +7036,8 @@ export type ResolversParentTypes = { OnChainUsdPaymentSendAsBtcDenominatedInput: OnChainUsdPaymentSendAsBtcDenominatedInput; OnChainUsdPaymentSendInput: OnChainUsdPaymentSendInput; OnChainUsdTxFee: OnChainUsdTxFee; + OnboardingFlowStartInput: OnboardingFlowStartInput; + OnboardingFlowStartResult: OnboardingFlowStartResult; OneDayAccountLimit: OneDayAccountLimit; OneTimeAuthCode: Scalars['OneTimeAuthCode']['output']; PageInfo: PageInfo; @@ -7028,14 +7115,67 @@ export type ResolversParentTypes = { WalletId: Scalars['WalletId']['output']; WelcomeLeaderboardInput: WelcomeLeaderboardInput; WelcomeProfile: WelcomeProfile; + join__FieldSet: Scalars['join__FieldSet']['output']; + link__Import: Scalars['link__Import']['output']; }; -export type DeferDirectiveArgs = { - if?: Scalars['Boolean']['input']; - label?: Maybe; +export type Join__EnumValueDirectiveArgs = { + graph: Join__Graph; }; -export type DeferDirectiveResolver = DirectiveResolverFn; +export type Join__EnumValueDirectiveResolver = DirectiveResolverFn; + +export type Join__FieldDirectiveArgs = { + external?: Maybe; + graph?: Maybe; + override?: Maybe; + provides?: Maybe; + requires?: Maybe; + type?: Maybe; + usedOverridden?: Maybe; +}; + +export type Join__FieldDirectiveResolver = DirectiveResolverFn; + +export type Join__GraphDirectiveArgs = { + name: Scalars['String']['input']; + url: Scalars['String']['input']; +}; + +export type Join__GraphDirectiveResolver = DirectiveResolverFn; + +export type Join__ImplementsDirectiveArgs = { + graph: Join__Graph; + interface: Scalars['String']['input']; +}; + +export type Join__ImplementsDirectiveResolver = DirectiveResolverFn; + +export type Join__TypeDirectiveArgs = { + extension?: Scalars['Boolean']['input']; + graph: Join__Graph; + isInterfaceObject?: Scalars['Boolean']['input']; + key?: Maybe; + resolvable?: Scalars['Boolean']['input']; +}; + +export type Join__TypeDirectiveResolver = DirectiveResolverFn; + +export type Join__UnionMemberDirectiveArgs = { + graph: Join__Graph; + member: Scalars['String']['input']; +}; + +export type Join__UnionMemberDirectiveResolver = DirectiveResolverFn; + +export type LinkDirectiveArgs = { + as?: Maybe; + for?: Maybe; + import?: Maybe>>; + url?: Maybe; +}; + +export type LinkDirectiveResolver = DirectiveResolverFn; export type AccountResolvers = { __resolveType: TypeResolveFn<'ConsumerAccount', ParentType, ContextType>; @@ -7447,6 +7587,7 @@ export type MutationResolvers>; onChainUsdPaymentSend?: Resolver>; onChainUsdPaymentSendAsBtcDenominated?: Resolver>; + onboardingFlowStart?: Resolver>; quizCompleted?: Resolver>; userContactUpdateAlias?: Resolver>; userEmailDelete?: Resolver; @@ -7521,6 +7662,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>; @@ -7619,6 +7767,7 @@ export type QueryResolvers; globals?: Resolver, ParentType, ContextType>; hasPromptedSetDefaultAccount?: Resolver; + hello?: Resolver, ParentType, ContextType>; hiddenBalanceToolTip?: Resolver; hideBalance?: Resolver; innerCircleValue?: Resolver; @@ -7935,6 +8084,14 @@ export type WelcomeProfileResolvers; }; +export interface Join__FieldSetScalarConfig extends GraphQLScalarTypeConfig { + name: 'join__FieldSet'; +} + +export interface Link__ImportScalarConfig extends GraphQLScalarTypeConfig { + name: 'link__Import'; +} + export type Resolvers = { Account?: AccountResolvers; AccountDeletePayload?: AccountDeletePayloadResolvers; @@ -8007,6 +8164,7 @@ export type Resolvers = { OnChainTxHash?: GraphQLScalarType; OnChainUpdate?: OnChainUpdateResolvers; OnChainUsdTxFee?: OnChainUsdTxFeeResolvers; + OnboardingFlowStartResult?: OnboardingFlowStartResultResolvers; OneDayAccountLimit?: OneDayAccountLimitResolvers; OneTimeAuthCode?: GraphQLScalarType; PageInfo?: PageInfoResolvers; @@ -8067,8 +8225,16 @@ export type Resolvers = { Wallet?: WalletResolvers; WalletId?: GraphQLScalarType; WelcomeProfile?: WelcomeProfileResolvers; + join__FieldSet?: GraphQLScalarType; + link__Import?: GraphQLScalarType; }; export type DirectiveResolvers = { - defer?: DeferDirectiveResolver; + join__enumValue?: Join__EnumValueDirectiveResolver; + join__field?: Join__FieldDirectiveResolver; + join__graph?: Join__GraphDirectiveResolver; + join__implements?: Join__ImplementsDirectiveResolver; + join__type?: Join__TypeDirectiveResolver; + join__unionMember?: Join__UnionMemberDirectiveResolver; + link?: LinkDirectiveResolver; }; diff --git a/app/i18n/en/index.ts b/app/i18n/en/index.ts index babf9a3c33..26ed406c7f 100644 --- a/app/i18n/en/index.ts +++ b/app/i18n/en/index.ts @@ -2409,12 +2409,8 @@ 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", + increaseLimitsLevel2: "Increase your limits by providing an ID", }, TransactionScreen: { noTransaction: "No transaction to show", @@ -2763,8 +2759,19 @@ 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: "Confirm your name", + 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: "To increase your limits, you will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", + accountVerifiedAlready: "You account has already been verified", + success: "Documents has been successfully received", + error: "There has been an error with the submission of your documents. You can contact the support is the problem persists." + } } export default en diff --git a/app/i18n/i18n-types.ts b/app/i18n/i18n-types.ts index ec91cf395d..ebc96950df 100644 --- a/app/i18n/i18n-types.ts +++ b/app/i18n/i18n-types.ts @@ -7501,23 +7501,14 @@ 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 */ increaseLimits: string + /** + * I​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​s​ ​b​y​ ​p​r​o​v​i​d​i​n​g​ ​a​n​ ​I​D + */ + increaseLimitsLevel2: string } TransactionScreen: { /** @@ -8658,6 +8649,50 @@ type RootTranslation = { fullDetails: string } } + FullOnboarding: { + /** + * F​u​l​l​ ​o​n​b​o​a​r​d​i​n​g + */ + title: string + /** + * C​o​n​f​i​r​m​ ​y​o​u​r​ ​n​a​m​e + */ + 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'> + /** + * T​o​ ​i​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​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 + /** + * Y​o​u​ ​a​c​c​o​u​n​t​ ​h​a​s​ ​a​l​r​e​a​d​y​ ​b​e​e​n​ ​v​e​r​i​f​i​e​d + */ + accountVerifiedAlready: 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 + */ + 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 + } } export type TranslationFunctions = { @@ -16078,22 +16113,14 @@ 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 */ increaseLimits: () => LocalizedString + /** + * Increase your limits by providing an ID + */ + increaseLimitsLevel2: () => LocalizedString } TransactionScreen: { /** @@ -17203,6 +17230,48 @@ export type TranslationFunctions = { fullDetails: () => LocalizedString } } + FullOnboarding: { + /** + * Full onboarding + */ + title: () => LocalizedString + /** + * Confirm your name + */ + 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 + /** + * To increase your limits, you will have to provide your name, a governement-issued ID and a selfie. We'll start with your name. + */ + requirements: () => LocalizedString + /** + * You account has already been verified + */ + accountVerifiedAlready: () => LocalizedString + /** + * Documents has been successfully received + */ + success: () => LocalizedString + /** + * There has been an error with the submission of your documents. You can contact the support is the problem persists. + */ + error: () => LocalizedString + } } export type Formatters = { diff --git a/app/i18n/raw-i18n/source/en.json b/app/i18n/raw-i18n/source/en.json index ebbd89f005..a8b21327c9 100644 --- a/app/i18n/raw-i18n/source/en.json +++ b/app/i18n/raw-i18n/source/en.json @@ -2333,10 +2333,8 @@ "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" + "increaseLimits": "Increase your limits", + "increaseLimitsLevel2": "Increase your limits by providing an ID" }, "TransactionScreen": { "noTransaction": "No transaction to show", @@ -2654,5 +2652,16 @@ "connectOnSocial": "Connect on social: ", "fullDetails": "Full details at " } + }, + "FullOnboarding": { + "title": "Full onboarding", + "confirmNameTitle": "Confirm your name", + "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": "To increase your limits, you will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", + "accountVerifiedAlready": "You account has already been verified", + "success": "Documents has been successfully received", + "error": "There has been an error with the submission of your documents. You can contact the support is the problem persists." } } diff --git a/app/navigation/root-navigator.tsx b/app/navigation/root-navigator.tsx index bd800ca42e..5b7ffd81a5 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 useStyles = makeStyles(({ colors }) => ({ bottomNavigatorStyle: { @@ -418,6 +419,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..ab843f3423 --- /dev/null +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx @@ -0,0 +1,20 @@ +import * as React from "react" +import { StoryScreen } from "../../../.storybook/views" +import { IsAuthedContextProvider } from "../../graphql/is-authed-context" +import { MockedProvider } from "@apollo/client/testing" +import { createCache } from "../../graphql/cache" +import { FullOnboardingFlowScreen } from "./full-onboarding-flow" + +export default { + title: "Full onboarding screen", + component: FullOnboardingFlowScreen, + decorators: [(Story) => {Story()}], +} + +export const Default = () => ( + + + + + +) 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..1e38e738ad --- /dev/null +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.tsx @@ -0,0 +1,168 @@ +import { gql } from "@apollo/client" +import { GaloyPrimaryButton } from "@app/components/atomic/galoy-primary-button" +import { Screen } from "@app/components/screen" +import { + useDebugScreenQuery, + useOnboardingFlowStartMutation, +} from "@app/graphql/generated" +import { AccountLevel, useLevel } from "@app/graphql/level-context" +import { useI18nContext } from "@app/i18n/i18n-react" +import { isIos } from "@app/utils/helper" +import Onfido, { OnfidoTheme } from "@onfido/react-native-sdk" +import { Input, Text, makeStyles } from "@rneui/themed" +import React, { useState } from "react" +import { Alert, View } from "react-native" + +gql` + mutation onboardingFlowStart($input: OnboardingFlowStartInput!) { + onboardingFlowStart(input: $input) { + workflowRunId + tokenAndroid + tokenIos + } + } + + query debugScreen { + me { + id + defaultAccount { + id + } + } + } +` + +export const FullOnboardingFlowScreen: React.FC = () => { + const { LL } = useI18nContext() + + const styles = useStyles() + styles + + const { currentLevel } = useLevel() + + const { data: dataDebug } = useDebugScreenQuery() + const accountId = dataDebug?.me?.defaultAccount?.id + + 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 = async () => { + if (!accountId) { + console.log("no account id") + return + } + + const res = await onboardingFlowStart({ + variables: { input: { accountId, 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 + const res = await Onfido.start({ + sdkToken, + theme: OnfidoTheme.AUTOMATIC, + workflowRunId, + }) + + Alert.alert(LL.FullOnboarding.success()) + console.log(res, "success") + } catch (err) { + Alert.alert(LL.FullOnboarding.error()) + console.log(err, "error") + } + } + + if (currentLevel === AccountLevel.Two) { + return ( + + + {LL.FullOnboarding.accountVerifiedAlready()} + + + ) + } + + return ( + + + {LL.FullOnboarding.requirements()} + setFirstName(text)} + /> + setLastName(text)} + /> + + + + ) +} + +const useStyles = makeStyles(() => ({ + view: { + marginHorizontal: 20, + padding: 20, + borderRadius: 20, + }, + + textHeader: { + fontSize: 18, + marginBottom: 24, + }, + + mainButton: { marginVertical: 20 }, + + screenContainer: { + marginHorizontal: 24, + marginVertical: 32, + }, +})) 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..dcfbdfe450 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/transaction-limits-screen.tsx b/app/screens/settings-screen/transaction-limits-screen.tsx index cba801fd95..fefc4e5253 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: { @@ -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()} - - - )} - 29.4.0) + - React - PromisesObjC (2.2.0) - PromisesSwift (2.2.0): - PromisesObjC (= 2.2.0) @@ -619,7 +623,7 @@ PODS: - React-Core - RNSVG (13.9.0): - React-Core - - RNVectorIcons (9.2.0): + - RNVectorIcons (10.0.0): - React-Core - vision-camera-code-scanner (0.2.0): - GoogleMLKit/BarcodeScanning @@ -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: @@ -923,6 +931,8 @@ SPEC CHECKSUMS: MLKitCommon: c1b791c3e667091918d91bda4bba69a91011e390 MLKitVision: 8baa5f46ee3352614169b85250574fde38c36f49 nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 + Onfido: abc5d9a0da1e3ae9f8b4a2a16cc1e77b7a38b12e + onfido-react-native-sdk: a62bb2bd5a8994ee29effc0412c013dfddf01f7e PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 @@ -986,7 +996,7 @@ SPEC CHECKSUMS: RNSecureRandom: 07efbdf2cd99efe13497433668e54acd7df49fef RNShare: da6d90b6dc332f51f86498041d6e34211f96b630 RNSVG: 53c661b76829783cdaf9b7a57258f3d3b4c28315 - RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 + RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 vision-camera-code-scanner: dda884a7f3ec8243a2a6d6489b91860648371bca VisionCamera: 523b49054bee9dace64189ab6631cb41e8b83fe0 Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 diff --git a/package.json b/package.json index 4797fe8c7e..ef42d1edc0 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "@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", 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..ba4465c513 100644 --- a/supergraph.graphql +++ b/supergraph.graphql @@ -560,6 +560,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 +797,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 +890,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 +986,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 +994,32 @@ 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) + userQuizQuestionUpdateCompleted(input: UserQuizQuestionUpdateCompletedInput!): UserQuizQuestionUpdateCompletedPayload! @join__field(graph: GALOY) @deprecated(reason: "Use QuizCompletedMutation instead") + 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 +1061,22 @@ type NotificationSettings push: NotificationChannelSettings! } +input OnboardingFlowStartInput + @join__type(graph: KYC) +{ + firstName: String! + lastName: String! + accountId: String! +} + +type OnboardingFlowStartResult + @join__type(graph: KYC) +{ + workflowRunId: String! + tokenAndroid: String! + tokenIos: String! +} + """An address for an on-chain bitcoin destination""" scalar OnChainAddress @join__type(graph: GALOY) @@ -1299,6 +1345,7 @@ 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) @@ -1319,6 +1366,7 @@ type Query realtimePrice(currency: DisplayCurrency = "USD"): RealtimePrice! @join__field(graph: GALOY) userDefaultWalletId(username: Username!): WalletId! @join__field(graph: GALOY) @deprecated(reason: "will be migrated to AccountDefaultWalletId") usernameAvailable(username: Username!): Boolean @join__field(graph: GALOY) + hello: String @join__field(graph: KYC) } type Quiz diff --git a/yarn.lock b/yarn.lock index a07454a1fd..062762a8bf 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" @@ -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" From dd3792eea41bef8fba33de84e5f085813128fd62 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Thu, 19 Oct 2023 14:42:51 +0100 Subject: [PATCH 2/5] chore: some iteration --- android/build.gradle | 2 +- app/graphql/generated.gql | 11 + app/graphql/generated.ts | 50 +++++ app/i18n/en/index.ts | 3 +- app/i18n/i18n-types.ts | 16 +- app/i18n/raw-i18n/source/en.json | 5 +- .../full-onboarding-flow.tsx | 41 ++-- .../send-bitcoin-details-extra-info.tsx | 2 +- .../settings-screen/account-screen.tsx | 9 + .../transaction-limits-screen.tsx | 4 +- ios/Podfile.lock | 192 +++++++++--------- package.json | 12 +- supergraph.graphql | 14 -- yarn.lock | 48 ++--- 14 files changed, 229 insertions(+), 180 deletions(-) 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/graphql/generated.gql b/app/graphql/generated.gql index 15bb802716..f1ba14919e 100644 --- a/app/graphql/generated.gql +++ b/app/graphql/generated.gql @@ -969,6 +969,17 @@ query feedbackModalShown { feedbackModalShown @client } +query fullOnboardingScreen { + me { + id + defaultAccount { + id + __typename + } + __typename + } +} + query hasPromptedSetDefaultAccount { hasPromptedSetDefaultAccount @client } diff --git a/app/graphql/generated.ts b/app/graphql/generated.ts index f12675c5d9..fc846cd44e 100644 --- a/app/graphql/generated.ts +++ b/app/graphql/generated.ts @@ -1283,6 +1283,8 @@ export type Query = { readonly __typename: 'Query'; readonly accountDefaultWallet: PublicWallet; readonly beta: Scalars['Boolean']['output']; + /** @deprecated Deprecated in favor of realtimePrice */ + readonly btcPrice?: Maybe; readonly btcPriceList?: Maybe>>; readonly businessMapMarkers?: Maybe>>; readonly colorScheme: Scalars['String']['output']; @@ -1319,6 +1321,11 @@ export type QueryAccountDefaultWalletArgs = { }; +export type QueryBtcPriceArgs = { + currency?: Scalars['DisplayCurrency']['input']; +}; + + export type QueryBtcPriceListArgs = { range: PriceGraphRange; }; @@ -2054,6 +2061,11 @@ export type OnboardingFlowStartMutationVariables = Exact<{ 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 } } | null }; + export type AddressScreenQueryVariables = Exact<{ [key: string]: never; }>; @@ -3761,6 +3773,43 @@ export function useOnboardingFlowStartMutation(baseOptions?: Apollo.MutationHook export type OnboardingFlowStartMutationHookResult = ReturnType; export type OnboardingFlowStartMutationResult = Apollo.MutationResult; export type OnboardingFlowStartMutationOptions = Apollo.BaseMutationOptions; +export const FullOnboardingScreenDocument = gql` + query fullOnboardingScreen { + me { + id + defaultAccount { + id + } + } +} + `; + +/** + * __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 { @@ -7760,6 +7809,7 @@ export type PublicWalletResolvers = { accountDefaultWallet?: Resolver>; beta?: Resolver; + btcPrice?: Resolver, ParentType, ContextType, RequireFields>; btcPriceList?: Resolver>>, ParentType, ContextType, RequireFields>; businessMapMarkers?: Resolver>>, ParentType, ContextType>; colorScheme?: Resolver; diff --git a/app/i18n/en/index.ts b/app/i18n/en/index.ts index 26ed406c7f..db8f7f4f69 100644 --- a/app/i18n/en/index.ts +++ b/app/i18n/en/index.ts @@ -2410,7 +2410,6 @@ const en: BaseTranslation = { internalSend: "Send to {bankName: string} User", error: "Unable to fetch limits at this time", increaseLimits: "Increase your limits", - increaseLimitsLevel2: "Increase your limits by providing an ID", }, TransactionScreen: { noTransaction: "No transaction to show", @@ -2767,7 +2766,7 @@ const en: BaseTranslation = { 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: "To increase your limits, you will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", + requirements: "Upgrading your account will increase your limits and give you additional functionality such as transfer to bank account, in selected countries.\n\nYou will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", accountVerifiedAlready: "You account has already been verified", success: "Documents has been successfully received", error: "There has been an error with the submission of your documents. You can contact the support is the problem persists." diff --git a/app/i18n/i18n-types.ts b/app/i18n/i18n-types.ts index ebc96950df..d6ef2bf115 100644 --- a/app/i18n/i18n-types.ts +++ b/app/i18n/i18n-types.ts @@ -7505,10 +7505,6 @@ type RootTranslation = { * I​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​s */ increaseLimits: string - /** - * I​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​s​ ​b​y​ ​p​r​o​v​i​d​i​n​g​ ​a​n​ ​I​D - */ - increaseLimitsLevel2: string } TransactionScreen: { /** @@ -8677,7 +8673,9 @@ type RootTranslation = { */ confirmNameContent: RequiredParams<'firstName' | 'lastName'> /** - * T​o​ ​i​n​c​r​e​a​s​e​ ​y​o​u​r​ ​l​i​m​i​t​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​. + * 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​,​ ​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 /** @@ -16117,10 +16115,6 @@ export type TranslationFunctions = { * Increase your limits */ increaseLimits: () => LocalizedString - /** - * Increase your limits by providing an ID - */ - increaseLimitsLevel2: () => LocalizedString } TransactionScreen: { /** @@ -17256,7 +17250,9 @@ export type TranslationFunctions = { */ confirmNameContent: (arg: { firstName: string, lastName: string }) => LocalizedString /** - * To increase your limits, you will have to provide your name, a governement-issued ID and a selfie. We'll start with your name. + * Upgrading your account will increase your limits and give you additional functionality such as transfer to bank account, 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 /** diff --git a/app/i18n/raw-i18n/source/en.json b/app/i18n/raw-i18n/source/en.json index a8b21327c9..99cbc0012b 100644 --- a/app/i18n/raw-i18n/source/en.json +++ b/app/i18n/raw-i18n/source/en.json @@ -2333,8 +2333,7 @@ "stablesatTransfers": "Stablesat Transfers", "internalSend": "Send to {bankName: string} User", "error": "Unable to fetch limits at this time", - "increaseLimits": "Increase your limits", - "increaseLimitsLevel2": "Increase your limits by providing an ID" + "increaseLimits": "Increase your limits" }, "TransactionScreen": { "noTransaction": "No transaction to show", @@ -2659,7 +2658,7 @@ "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": "To increase your limits, you will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", + "requirements": "Upgrading your account will increase your limits and give you additional functionality such as transfer to bank account, in selected countries.\n\nYou will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", "accountVerifiedAlready": "You account has already been verified", "success": "Documents has been successfully received", "error": "There has been an error with the submission of your documents. You can contact the support is the problem persists." diff --git a/app/screens/full-onboarding-flow/full-onboarding-flow.tsx b/app/screens/full-onboarding-flow/full-onboarding-flow.tsx index 1e38e738ad..7cc8202c5e 100644 --- a/app/screens/full-onboarding-flow/full-onboarding-flow.tsx +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.tsx @@ -2,7 +2,7 @@ import { gql } from "@apollo/client" import { GaloyPrimaryButton } from "@app/components/atomic/galoy-primary-button" import { Screen } from "@app/components/screen" import { - useDebugScreenQuery, + useFullOnboardingScreenQuery, useOnboardingFlowStartMutation, } from "@app/graphql/generated" import { AccountLevel, useLevel } from "@app/graphql/level-context" @@ -22,7 +22,7 @@ gql` } } - query debugScreen { + query fullOnboardingScreen { me { id defaultAccount { @@ -36,12 +36,11 @@ export const FullOnboardingFlowScreen: React.FC = () => { const { LL } = useI18nContext() const styles = useStyles() - styles const { currentLevel } = useLevel() - const { data: dataDebug } = useDebugScreenQuery() - const accountId = dataDebug?.me?.defaultAccount?.id + const { data } = useFullOnboardingScreenQuery() + const accountId = data?.me?.defaultAccount?.id const [onboardingFlowStart] = useOnboardingFlowStartMutation() @@ -111,10 +110,9 @@ export const FullOnboardingFlowScreen: React.FC = () => { preset="scroll" keyboardShouldPersistTaps="handled" keyboardOffset="navigationHeader" + style={styles.screenStyle} > - - {LL.FullOnboarding.accountVerifiedAlready()} - + {LL.FullOnboarding.accountVerifiedAlready()} ) } @@ -124,9 +122,12 @@ export const FullOnboardingFlowScreen: React.FC = () => { preset="scroll" keyboardShouldPersistTaps="handled" keyboardOffset="navigationHeader" + style={styles.screenStyle} > - - {LL.FullOnboarding.requirements()} + + {LL.FullOnboarding.requirements()} + + <> { value={lastName} onChangeText={(text) => setLastName(text)} /> + + { } const useStyles = makeStyles(() => ({ - view: { - marginHorizontal: 20, + screenStyle: { padding: 20, - borderRadius: 20, + flexGrow: 1, }, - textHeader: { - fontSize: 18, - marginBottom: 24, + textStyle: { + marginBottom: 32, }, - mainButton: { marginVertical: 20 }, - - screenContainer: { - marginHorizontal: 24, - marginVertical: 32, + buttonContainer: { + flex: 1, + justifyContent: "flex-end", }, })) 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 dcfbdfe450..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 @@ -62,7 +62,7 @@ export const SendBitcoinDetailsExtraInfo = ({ ) : null} {currentLevel === "ONE" ? ( navigation.navigate("fullOnboardingFlow")} /> ) : null} diff --git a/app/screens/settings-screen/account-screen.tsx b/app/screens/settings-screen/account-screen.tsx index d5b7fe57f6..945e985005 100644 --- a/app/screens/settings-screen/account-screen.tsx +++ b/app/screens/settings-screen/account-screen.tsx @@ -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 fefc4e5253..87cd0444c0 100644 --- a/app/screens/settings-screen/transaction-limits-screen.tsx +++ b/app/screens/settings-screen/transaction-limits-screen.tsx @@ -25,7 +25,7 @@ const useStyles = makeStyles(({ colors }) => ({ }, increaseLimitsButtonContainer: { marginVertical: 20, - paddingHorizontal: 20, + marginHorizontal: 20, }, contentTextBox: { flexDirection: "row", @@ -226,7 +226,7 @@ export const TransactionLimitsScreen = () => { )} {currentLevel === AccountLevel.One && ( navigation.navigate("fullOnboardingFlow")} containerStyle={styles.increaseLimitsButtonContainer} /> diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 19d23152e9..f31bb19282 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,47 +11,47 @@ PODS: - React-Core (= 0.71.8) - React-jsi (= 0.71.8) - ReactCommon/turbomodule/core (= 0.71.8) - - Firebase/AnalyticsWithoutAdIdSupport (10.7.0): + - Firebase/AnalyticsWithoutAdIdSupport (10.15.0): - Firebase/CoreOnly - - FirebaseAnalytics/WithoutAdIdSupport (~> 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,13 +166,13 @@ PODS: - nanopb/encode (= 2.30909.0) - nanopb/decode (2.30909.0) - nanopb/encode (2.30909.0) - - Onfido (29.4.2) - - onfido-react-native-sdk (10.3.1): - - Onfido (~> 29.4.0) + - Onfido (29.5.1) + - onfido-react-native-sdk (10.4.0): + - Onfido (~> 29.5.0) - React - - PromisesObjC (2.2.0) - - PromisesSwift (2.2.0): - - PromisesObjC (= 2.2.0) + - PromisesObjC (2.3.1) + - PromisesSwift (2.3.1): + - PromisesObjC (= 2.3.1) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -547,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): @@ -623,7 +623,7 @@ PODS: - React-Core - RNSVG (13.9.0): - React-Core - - RNVectorIcons (10.0.0): + - RNVectorIcons (9.2.0): - React-Core - vision-camera-code-scanner (0.2.0): - GoogleMLKit/BarcodeScanning @@ -633,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`) @@ -902,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 @@ -931,10 +931,10 @@ SPEC CHECKSUMS: MLKitCommon: c1b791c3e667091918d91bda4bba69a91011e390 MLKitVision: 8baa5f46ee3352614169b85250574fde38c36f49 nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 - Onfido: abc5d9a0da1e3ae9f8b4a2a16cc1e77b7a38b12e - onfido-react-native-sdk: a62bb2bd5a8994ee29effc0412c013dfddf01f7e - PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef - PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959 + Onfido: 9f2d7e79ee300783a0359a902accf1b6e10e8c26 + onfido-react-native-sdk: 62867f1949c559dec9cb235eae09ca039528a0af + PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 + PromisesSwift: 28dca69a9c40779916ac2d6985a0192a5cb4a265 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: 8af6a32dfc2b65ec82193c2dee6e1011ff22ac2a RCTTypeSafety: bee9dd161c175896c680d47ef1d9eaacf2b587f4 @@ -978,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 @@ -996,12 +996,12 @@ SPEC CHECKSUMS: RNSecureRandom: 07efbdf2cd99efe13497433668e54acd7df49fef RNShare: da6d90b6dc332f51f86498041d6e34211f96b630 RNSVG: 53c661b76829783cdaf9b7a57258f3d3b4c28315 - RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 + RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 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 ef42d1edc0..ebfeee89ee 100644 --- a/package.json +++ b/package.json @@ -63,12 +63,12 @@ "@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.graphql b/supergraph.graphql index ba4465c513..809c716fc5 100644 --- a/supergraph.graphql +++ b/supergraph.graphql @@ -1013,7 +1013,6 @@ type Mutation userPhoneDelete: UserPhoneDeletePayload! @join__field(graph: GALOY) userPhoneRegistrationInitiate(input: UserPhoneRegistrationInitiateInput!): SuccessPayload! @join__field(graph: GALOY) userPhoneRegistrationValidate(input: UserPhoneRegistrationValidateInput!): UserPhoneRegistrationValidatePayload! @join__field(graph: GALOY) - userQuizQuestionUpdateCompleted(input: UserQuizQuestionUpdateCompletedInput!): UserQuizQuestionUpdateCompletedPayload! @join__field(graph: GALOY) @deprecated(reason: "Use QuizCompletedMutation instead") userTotpDelete(input: UserTotpDeleteInput!): UserTotpDeletePayload! @join__field(graph: GALOY) userTotpRegistrationInitiate(input: UserTotpRegistrationInitiateInput!): UserTotpRegistrationInitiatePayload! @join__field(graph: GALOY) userTotpRegistrationValidate(input: UserTotpRegistrationValidateInput!): UserTotpRegistrationValidatePayload! @join__field(graph: GALOY) @@ -1839,19 +1838,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 062762a8bf..4681a88ad7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4242,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" From 5141d3a663a699b1e6d457b484cf85ef17f625a8 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Thu, 19 Oct 2023 15:50:30 +0100 Subject: [PATCH 3/5] fix: type --- app/components/notification/notification.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) 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) } } From 9bc31fb983d5e3a292d266ac33353f36cc3d9ccd Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Thu, 19 Oct 2023 20:56:46 +0100 Subject: [PATCH 4/5] chore: make build work --- android/app/build.gradle | 13 ++ .../contact-support-button.tsx | 2 +- app/graphql/generated.gql | 6 +- app/graphql/generated.ts | 133 ++++-------------- app/i18n/en/index.ts | 16 ++- app/i18n/i18n-types.ts | 80 ++++++++--- app/i18n/raw-i18n/source/en.json | 16 ++- .../full-onboarding-flow.stories.tsx | 56 +++++++- .../full-onboarding-flow.tsx | 110 ++++++++++++--- codegen.yml | 4 +- supergraph.graphql | 18 ++- 11 files changed, 286 insertions(+), 168 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 53fc908c36..67cbafa16d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -151,6 +151,12 @@ android { } } } + + configurations.all { + resolutionStrategy { + force 'com.google.android.play:core-common:2.0.2' + } + } } dependencies { @@ -173,6 +179,13 @@ dependencies { 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' } 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/graphql/generated.gql b/app/graphql/generated.gql index f1ba14919e..f884df85f2 100644 --- a/app/graphql/generated.gql +++ b/app/graphql/generated.gql @@ -973,7 +973,11 @@ query fullOnboardingScreen { me { id defaultAccount { - id + ... on ConsumerAccount { + id + onboardingStatus + __typename + } __typename } __typename diff --git a/app/graphql/generated.ts b/app/graphql/generated.ts index fc846cd44e..ca838ee39f 100644 --- a/app/graphql/generated.ts +++ b/app/graphql/generated.ts @@ -82,8 +82,6 @@ export type Scalars = { Username: { input: string; output: string; } /** Unique identifier of a wallet */ WalletId: { input: string; output: string; } - join__FieldSet: { input: string; output: string; } - link__Import: { input: string; output: string; } _FieldSet: { input: string; output: string; } }; @@ -303,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; @@ -1138,7 +1137,6 @@ export type OnChainUsdTxFee = { }; export type OnboardingFlowStartInput = { - readonly accountId: Scalars['String']['input']; readonly firstName: Scalars['String']['input']; readonly lastName: Scalars['String']['input']; }; @@ -1150,6 +1148,18 @@ export type OnboardingFlowStartResult = { 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. */ @@ -1283,8 +1293,6 @@ export type Query = { readonly __typename: 'Query'; readonly accountDefaultWallet: PublicWallet; readonly beta: Scalars['Boolean']['output']; - /** @deprecated Deprecated in favor of realtimePrice */ - readonly btcPrice?: Maybe; readonly btcPriceList?: Maybe>>; readonly businessMapMarkers?: Maybe>>; readonly colorScheme: Scalars['String']['output']; @@ -1292,7 +1300,6 @@ export type Query = { readonly feedbackModalShown: Scalars['Boolean']['output']; readonly globals?: Maybe; readonly hasPromptedSetDefaultAccount: Scalars['Boolean']['output']; - readonly hello?: Maybe; readonly hiddenBalanceToolTip: Scalars['Boolean']['output']; readonly hideBalance: Scalars['Boolean']['output']; readonly innerCircleValue: Scalars['Int']['output']; @@ -1321,11 +1328,6 @@ export type QueryAccountDefaultWalletArgs = { }; -export type QueryBtcPriceArgs = { - currency?: Scalars['DisplayCurrency']['input']; -}; - - export type QueryBtcPriceListArgs = { range: PriceGraphRange; }; @@ -1868,21 +1870,6 @@ export const WelcomeRange = { } as const; export type WelcomeRange = typeof WelcomeRange[keyof typeof WelcomeRange]; -export const Join__Graph = { - Circles: 'CIRCLES', - Galoy: 'GALOY', - Kyc: 'KYC' -} as const; - -export type Join__Graph = typeof Join__Graph[keyof typeof Join__Graph]; -export const Link__Purpose = { - /** `EXECUTION` features provide metadata necessary for operation execution. */ - Execution: 'EXECUTION', - /** `SECURITY` features provide metadata necessary to securely resolve fields. */ - Security: 'SECURITY' -} as const; - -export type Link__Purpose = typeof Link__Purpose[keyof typeof Link__Purpose]; export type MobileUpdateQueryVariables = Exact<{ [key: string]: never; }>; @@ -2064,7 +2051,7 @@ export type OnboardingFlowStartMutation = { readonly __typename: 'Mutation', rea 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 } } | null }; +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; }>; @@ -3778,7 +3765,10 @@ export const FullOnboardingScreenDocument = gql` me { id defaultAccount { - id + ... on ConsumerAccount { + id + onboardingStatus + } } } } @@ -6881,6 +6871,7 @@ export type ResolversTypes = { OnChainUsdTxFee: ResolverTypeWrapper; OnboardingFlowStartInput: OnboardingFlowStartInput; OnboardingFlowStartResult: ResolverTypeWrapper; + OnboardingStatus: OnboardingStatus; OneDayAccountLimit: ResolverTypeWrapper; OneTimeAuthCode: ResolverTypeWrapper; PageInfo: ResolverTypeWrapper; @@ -6967,10 +6958,6 @@ export type ResolversTypes = { WelcomeLeaderboardInput: WelcomeLeaderboardInput; WelcomeProfile: ResolverTypeWrapper; WelcomeRange: WelcomeRange; - join__FieldSet: ResolverTypeWrapper; - join__Graph: Join__Graph; - link__Import: ResolverTypeWrapper; - link__Purpose: Link__Purpose; }; /** Mapping between all available schema types and the resolvers parents */ @@ -7164,67 +7151,14 @@ export type ResolversParentTypes = { WalletId: Scalars['WalletId']['output']; WelcomeLeaderboardInput: WelcomeLeaderboardInput; WelcomeProfile: WelcomeProfile; - join__FieldSet: Scalars['join__FieldSet']['output']; - link__Import: Scalars['link__Import']['output']; }; -export type Join__EnumValueDirectiveArgs = { - graph: Join__Graph; +export type DeferDirectiveArgs = { + if?: Scalars['Boolean']['input']; + label?: Maybe; }; -export type Join__EnumValueDirectiveResolver = DirectiveResolverFn; - -export type Join__FieldDirectiveArgs = { - external?: Maybe; - graph?: Maybe; - override?: Maybe; - provides?: Maybe; - requires?: Maybe; - type?: Maybe; - usedOverridden?: Maybe; -}; - -export type Join__FieldDirectiveResolver = DirectiveResolverFn; - -export type Join__GraphDirectiveArgs = { - name: Scalars['String']['input']; - url: Scalars['String']['input']; -}; - -export type Join__GraphDirectiveResolver = DirectiveResolverFn; - -export type Join__ImplementsDirectiveArgs = { - graph: Join__Graph; - interface: Scalars['String']['input']; -}; - -export type Join__ImplementsDirectiveResolver = DirectiveResolverFn; - -export type Join__TypeDirectiveArgs = { - extension?: Scalars['Boolean']['input']; - graph: Join__Graph; - isInterfaceObject?: Scalars['Boolean']['input']; - key?: Maybe; - resolvable?: Scalars['Boolean']['input']; -}; - -export type Join__TypeDirectiveResolver = DirectiveResolverFn; - -export type Join__UnionMemberDirectiveArgs = { - graph: Join__Graph; - member: Scalars['String']['input']; -}; - -export type Join__UnionMemberDirectiveResolver = DirectiveResolverFn; - -export type LinkDirectiveArgs = { - as?: Maybe; - for?: Maybe; - import?: Maybe>>; - url?: Maybe; -}; - -export type LinkDirectiveResolver = DirectiveResolverFn; +export type DeferDirectiveResolver = DirectiveResolverFn; export type AccountResolvers = { __resolveType: TypeResolveFn<'ConsumerAccount', ParentType, ContextType>; @@ -7357,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>; @@ -7809,7 +7744,6 @@ export type PublicWalletResolvers = { accountDefaultWallet?: Resolver>; beta?: Resolver; - btcPrice?: Resolver, ParentType, ContextType, RequireFields>; btcPriceList?: Resolver>>, ParentType, ContextType, RequireFields>; businessMapMarkers?: Resolver>>, ParentType, ContextType>; colorScheme?: Resolver; @@ -7817,7 +7751,6 @@ export type QueryResolvers; globals?: Resolver, ParentType, ContextType>; hasPromptedSetDefaultAccount?: Resolver; - hello?: Resolver, ParentType, ContextType>; hiddenBalanceToolTip?: Resolver; hideBalance?: Resolver; innerCircleValue?: Resolver; @@ -8134,14 +8067,6 @@ export type WelcomeProfileResolvers; }; -export interface Join__FieldSetScalarConfig extends GraphQLScalarTypeConfig { - name: 'join__FieldSet'; -} - -export interface Link__ImportScalarConfig extends GraphQLScalarTypeConfig { - name: 'link__Import'; -} - export type Resolvers = { Account?: AccountResolvers; AccountDeletePayload?: AccountDeletePayloadResolvers; @@ -8275,16 +8200,8 @@ export type Resolvers = { Wallet?: WalletResolvers; WalletId?: GraphQLScalarType; WelcomeProfile?: WelcomeProfileResolvers; - join__FieldSet?: GraphQLScalarType; - link__Import?: GraphQLScalarType; }; export type DirectiveResolvers = { - join__enumValue?: Join__EnumValueDirectiveResolver; - join__field?: Join__FieldDirectiveResolver; - join__graph?: Join__GraphDirectiveResolver; - join__implements?: Join__ImplementsDirectiveResolver; - join__type?: Join__TypeDirectiveResolver; - join__unionMember?: Join__UnionMemberDirectiveResolver; - link?: LinkDirectiveResolver; + defer?: DeferDirectiveResolver; }; diff --git a/app/i18n/en/index.ts b/app/i18n/en/index.ts index db8f7f4f69..f0614d943a 100644 --- a/app/i18n/en/index.ts +++ b/app/i18n/en/index.ts @@ -2762,14 +2762,20 @@ const en: BaseTranslation = { }, FullOnboarding: { title: "Full onboarding", - confirmNameTitle: "Confirm your name", + 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 account, in selected countries.\n\nYou will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", - accountVerifiedAlready: "You account has already been verified", - success: "Documents has been successfully received", - error: "There has been an error with the submission of your documents. You can contact the support is the problem persists." + 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/i18n/i18n-types.ts b/app/i18n/i18n-types.ts index d6ef2bf115..2dc09a797a 100644 --- a/app/i18n/i18n-types.ts +++ b/app/i18n/i18n-types.ts @@ -8651,7 +8651,7 @@ type RootTranslation = { */ title: string /** - * C​o​n​f​i​r​m​ ​y​o​u​r​ ​n​a​m​e + * N​a​m​e​ ​c​o​n​f​i​r​m​a​t​i​o​n */ confirmNameTitle: string /** @@ -8673,23 +8673,47 @@ type RootTranslation = { */ 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​,​ ​i​n​ ​s​e​l​e​c​t​e​d​ ​c​o​u​n​t​r​i​e​s​.​ + * 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​. + ​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 /** - * Y​o​u​ ​a​c​c​o​u​n​t​ ​h​a​s​ ​a​l​r​e​a​d​y​ ​b​e​e​n​ ​v​e​r​i​f​i​e​d - */ - accountVerifiedAlready: 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 + * 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 } } @@ -17230,7 +17254,7 @@ export type TranslationFunctions = { */ title: () => LocalizedString /** - * Confirm your name + * Name confirmation */ confirmNameTitle: () => LocalizedString /** @@ -17250,23 +17274,47 @@ export type TranslationFunctions = { */ confirmNameContent: (arg: { firstName: string, lastName: string }) => LocalizedString /** - * Upgrading your account will increase your limits and give you additional functionality such as transfer to bank account, in selected countries. + * 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. + You will have to provide your name, a governement issued ID and a selfie. We'll start with your name. */ requirements: () => LocalizedString /** - * You account has already been verified - */ - accountVerifiedAlready: () => LocalizedString - /** - * Documents has been successfully received + * 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 } } diff --git a/app/i18n/raw-i18n/source/en.json b/app/i18n/raw-i18n/source/en.json index 99cbc0012b..a3eb61d018 100644 --- a/app/i18n/raw-i18n/source/en.json +++ b/app/i18n/raw-i18n/source/en.json @@ -2654,13 +2654,19 @@ }, "FullOnboarding": { "title": "Full onboarding", - "confirmNameTitle": "Confirm your name", + "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 account, in selected countries.\n\nYou will have to provide your name, a governement-issued ID and a selfie. We'll start with your name.", - "accountVerifiedAlready": "You account has already been verified", - "success": "Documents has been successfully received", - "error": "There has been an error with the submission of your documents. You can contact the support is the problem persists." + "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/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx b/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx index ab843f3423..25082b2563 100644 --- a/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.stories.tsx @@ -1,9 +1,9 @@ import * as React from "react" import { StoryScreen } from "../../../.storybook/views" -import { IsAuthedContextProvider } from "../../graphql/is-authed-context" 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", @@ -11,10 +11,56 @@ export default { 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 index 7cc8202c5e..d02be9ac4e 100644 --- a/app/screens/full-onboarding-flow/full-onboarding-flow.tsx +++ b/app/screens/full-onboarding-flow/full-onboarding-flow.tsx @@ -1,17 +1,19 @@ 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 { AccountLevel, useLevel } from "@app/graphql/level-context" import { useI18nContext } from "@app/i18n/i18n-react" import { isIos } from "@app/utils/helper" import Onfido, { OnfidoTheme } from "@onfido/react-native-sdk" -import { Input, Text, makeStyles } from "@rneui/themed" -import React, { useState } from "react" -import { Alert, View } from "react-native" +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!) { @@ -26,21 +28,29 @@ gql` me { id defaultAccount { - id + ... on ConsumerAccount { + id + onboardingStatus + } } } } ` export const FullOnboardingFlowScreen: React.FC = () => { + const navigation = useNavigation() + const { LL } = useI18nContext() + const { + theme: { colors }, + } = useTheme() + const styles = useStyles() - const { currentLevel } = useLevel() + const { data, loading } = useFullOnboardingScreenQuery({ fetchPolicy: "network-only" }) - const { data } = useFullOnboardingScreenQuery() - const accountId = data?.me?.defaultAccount?.id + const onboardingStatus = data?.me?.defaultAccount?.onboardingStatus const [onboardingFlowStart] = useOnboardingFlowStartMutation() @@ -61,14 +71,9 @@ export const FullOnboardingFlowScreen: React.FC = () => { ) } - const onfidoStart = async () => { - if (!accountId) { - console.log("no account id") - return - } - + const onfidoStart = React.useCallback(async () => { const res = await onboardingFlowStart({ - variables: { input: { accountId, firstName, lastName } }, + variables: { input: { firstName, lastName } }, }) const workflowRunId = res.data?.onboardingFlowStart?.workflowRunId @@ -90,21 +95,76 @@ export const FullOnboardingFlowScreen: React.FC = () => { try { /* eslint @typescript-eslint/ban-ts-comment: "off" */ // @ts-expect-error - const res = await Onfido.start({ + await Onfido.start({ sdkToken, theme: OnfidoTheme.AUTOMATIC, workflowRunId, }) - Alert.alert(LL.FullOnboarding.success()) - console.log(res, "success") + Alert.alert(LL.common.success(), LL.FullOnboarding.success(), [ + { + text: LL.common.ok(), + onPress: () => { + navigation.goBack() + }, + }, + ]) } catch (err) { - Alert.alert(LL.FullOnboarding.error()) - console.log(err, "error") + 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 (currentLevel === AccountLevel.Two) { + if ( + onboardingStatus === OnboardingStatus.Abandoned || + onboardingStatus === OnboardingStatus.Approved || + onboardingStatus === OnboardingStatus.Declined || + onboardingStatus === OnboardingStatus.Error || + onboardingStatus === OnboardingStatus.Processing || + onboardingStatus === OnboardingStatus.Review + ) { return ( { keyboardOffset="navigationHeader" style={styles.screenStyle} > - {LL.FullOnboarding.accountVerifiedAlready()} + {`${LL.FullOnboarding.status()}${LL.FullOnboarding[onboardingStatus]()}.`} + ) } @@ -164,4 +228,6 @@ const useStyles = makeStyles(() => ({ flex: 1, justifyContent: "flex-end", }, + + verticalAlignment: { flex: 1, justifyContent: "center", alignItems: "center" }, })) diff --git a/codegen.yml b/codegen.yml index 01995dfb81..93481ed72a 100644 --- a/codegen.yml +++ b/codegen.yml @@ -1,6 +1,6 @@ overwrite: true -# schema: "https://api.staging.galoy.io/graphql" -schema: "./supergraph.graphql" +schema: "https://api.staging.galoy.io/graphql" +# schema: "./supergraph.graphql" documents: - "app/**/*.ts" - "app/**/*.tsx" diff --git a/supergraph.graphql b/supergraph.graphql index 809c716fc5..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) } """ @@ -1065,7 +1067,6 @@ input OnboardingFlowStartInput { firstName: String! lastName: String! - accountId: String! } type OnboardingFlowStartResult @@ -1076,6 +1077,19 @@ type OnboardingFlowStartResult 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) @@ -1348,7 +1362,6 @@ type Query { 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) @@ -1365,7 +1378,6 @@ type Query realtimePrice(currency: DisplayCurrency = "USD"): RealtimePrice! @join__field(graph: GALOY) userDefaultWalletId(username: Username!): WalletId! @join__field(graph: GALOY) @deprecated(reason: "will be migrated to AccountDefaultWalletId") usernameAvailable(username: Username!): Boolean @join__field(graph: GALOY) - hello: String @join__field(graph: KYC) } type Quiz From 4f712f27852fed8b2956c9635d0150850b6730e7 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Mon, 23 Oct 2023 14:19:36 +0100 Subject: [PATCH 5/5] chore: update level when going to account screen --- app/screens/settings-screen/account-screen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/screens/settings-screen/account-screen.tsx b/app/screens/settings-screen/account-screen.tsx index 945e985005..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, })