Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
6613043
feat: clean up oauth service
ieow Jun 26, 2025
d1465f8
fix: remove build flag
ieow Jun 26, 2025
e08a4ca
fix: remove unused added assets
ieow Jun 26, 2025
9554498
fix: oauth config
ieow Jun 27, 2025
6a7aca4
chore: address comment
ieow Jun 27, 2025
78bc655
fix : check for getBundleId
ieow Jun 27, 2025
ee72c36
fix: default ios google client bundleid
ieow Jun 27, 2025
20b3a03
fix: remove oauth env from js.env.example
ieow Jun 27, 2025
a4950c6
feat: implement onboarding sheet and account status screens
ieow Jun 27, 2025
f929f36
fix: add OTHER_METHODS_BUTTON selector to LoginView
ieow Jun 27, 2025
0eecdd9
feat: remove seedless onboarding Build Flag from Login, Onboarding, a…
ieow Jun 27, 2025
375660c
fix: update snapshot
ieow Jun 27, 2025
ebbeaab
test: enhance Login component tests with authentication scenarios
huggingbot Jun 27, 2025
d365d5d
fix: Failing tests in Onboarding view after merge
huggingbot Jun 28, 2025
a4649ef
test: enhance App component tests with onboarding navigation scenarios
huggingbot Jun 28, 2025
db0af35
test: add tests for SOLANA_DISCOVERY_PENDING handling in wallet creat…
huggingbot Jun 29, 2025
368ff2c
test: add rehydrateSeedPhrase tests for seed phrase handling in Authe…
huggingbot Jun 29, 2025
6cea7a3
fix: seedless onboarding runtime env
ieow Jun 30, 2025
bbbfdc1
feat: seedless change password
ieow Jun 30, 2025
320c8a3
fix: test case update
smgv Jun 30, 2025
4b17a02
test: enhance Onboarding tests with OAuth login scenarios and seedles…
huggingbot Jun 30, 2025
4881cee
fix: test update
smgv Jun 30, 2025
e4109ff
feat: init with default state when env is not enabled
ieow Jun 30, 2025
e9f01e2
feat: buildtype mapping
ieow Jun 30, 2025
938221f
feat: browser bff apple flow
ieow Jun 30, 2025
be70766
fix: address comment
ieow Jul 1, 2025
9de4ee4
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 1, 2025
1ca4d2c
fix: update config
ieow Jul 1, 2025
e13a58c
fix: address comment, update config
ieow Jul 1, 2025
719fb5f
fix: remove console.log
ieow Jul 1, 2025
be62797
fix: extension parity
ieow Jul 1, 2025
b5ca197
chore: move client id out of config
ieow Jul 1, 2025
e293c2c
fix: update acm with main commit
ieow Jul 1, 2025
8f8acb1
fix: update acm with main commit
ieow Jul 1, 2025
0a15e01
fix: mock base handler
ieow Jul 1, 2025
66575f9
fix: tests
ieow Jul 1, 2025
252f54c
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 1, 2025
d2757b1
fix: push coverage
ieow Jul 1, 2025
86ff499
fix: add test for getAuthToken
ieow Jul 1, 2025
37bc2fe
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 1, 2025
ee181ef
fix: revert controller default state
ieow Jul 1, 2025
9a62ef1
Merge branch 'feat/new-srp-oauth-service' into feat/oauth-clientId
ieow Jul 1, 2025
7210473
feat: add
ieow Jul 1, 2025
752057d
fix: address comment
ieow Jul 1, 2025
73c0269
fix: test
ieow Jul 1, 2025
d2ef5cf
fix: mock react-native-quick-crypto
ieow Jul 1, 2025
20c041c
fix: lint
ieow Jul 1, 2025
f3ee809
chroe: remaping buildtype env
ieow Jul 1, 2025
2b07291
Merge branch 'feat/new-srp-oauth-service' into feat/oauth-clientId
ieow Jul 1, 2025
5f0d3e6
Feat/oauth-clientId (#16823)
ieow Jul 1, 2025
72d4270
Merge branch 'main' into feat/new-srp-oauth-service
ieow Jul 1, 2025
3ed6713
fix: bff start with authserver url
ieow Jul 1, 2025
d883ecd
fix: use base64 url for pcke
ieow Jul 1, 2025
376dfd9
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 2, 2025
3b31a10
fix: update with mm authserver flow
ieow Jul 2, 2025
d8a95e4
chore: update example with mm dev client id
ieow Jul 2, 2025
770b11d
fix: update with mm authserver flow
ieow Jul 2, 2025
0d5faf3
chore: update example with mm dev client id
ieow Jul 2, 2025
8e2d09b
fix code class
chaitanyapotti Jul 2, 2025
d8c160c
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 2, 2025
c1f3457
fix: bff and typing
ieow Jul 2, 2025
1347354
fix: bff and typing
ieow Jul 2, 2025
5c904cd
fix: remapping prod variable for seedless onboarding
ieow Jul 2, 2025
b0c3a51
fix: remapping prod variable for seedless onboarding
ieow Jul 2, 2025
e08f820
fix: tests
ieow Jul 2, 2025
1c4e6ff
fix: tests
ieow Jul 2, 2025
21d9ae3
fix: lint
ieow Jul 2, 2025
56369f5
fix: update with qa env checking for buildtype
ieow Jul 2, 2025
fe7300b
fix: js.env.example
ieow Jul 2, 2025
dd55df2
fix: lint
ieow Jul 2, 2025
2697abf
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 2, 2025
f10f091
chore: remove ignored lefthook.yml
ieow Jul 2, 2025
12d1fa8
fix: update snapshot
ieow Jul 2, 2025
aadd3e4
Merge branch 'main' into feat/new-srp-oauth-service
chaitanyapotti Jul 2, 2025
1e53a6e
Merge branch 'main' into feat/new-srp-oauth-service
hieu-w Jul 2, 2025
7b7db7b
test: fix flaky scroll to element util
hieu-w Jul 2, 2025
d6a525c
Merge branch 'main' into feat/new-srp-oauth-service
hieu-w Jul 2, 2025
f005fda
test: revert ImportWalletView page object to latest
hieu-w Jul 2, 2025
7a33662
Merge branch 'main' into feat/new-srp-oauth-service
chaitanyapotti Jul 3, 2025
65737d9
Revert "test: fix flaky scroll to element util"
hieu-w Jul 3, 2025
113232c
Merge branch 'feat/new-srp-oauth-service' into feat/seedless-oauth-flow
ieow Jul 3, 2025
df66a5b
fix: update snapshot
ieow Jul 3, 2025
08d11c6
fix: checkbox
ieow Jul 3, 2025
9d4c33a
fix: update snapshot
ieow Jul 3, 2025
22b4273
fix: use uint8ArrayToMnemonic
ieow Jul 3, 2025
0968a9e
fix: parity with delete(reset) wallet
ieow Jul 3, 2025
5644646
Merge branch 'main' into feat/seedless-oauth-flow
ieow Jul 3, 2025
b33d4b1
fix: mock uint8ArrayToMnemonic in tests
ieow Jul 3, 2025
3ed88f6
Merge branch 'main' into feat/seedless-oauth-flow
ieow Jul 3, 2025
cfc051b
fix: merge conflict
ieow Jul 3, 2025
da997f8
fix: update snapshot
ieow Jul 3, 2025
0aa8cfe
fix: remove Recursion function
ieow Jul 3, 2025
e743347
fix: update snapshot
ieow Jul 3, 2025
b291d4f
fix: show error and fix parameter mistmatch
ieow Jul 3, 2025
50a7d12
fix: Unmounted Component State Update
ieow Jul 3, 2025
ea0abd0
fix: share client id for ios*,android and extension
ieow Jul 4, 2025
1aef3b2
Merge branch 'feat/seedless-oauth-flow' into feat/seedless-change-pw
ieow Jul 4, 2025
a2f0079
feat: check for is QA first
ieow Jul 4, 2025
661d816
fix: testcase
ieow Jul 4, 2025
5b9350b
Merge branch 'feat/seedless-oauth-flow' into feat/seedless-change-pw
hieu-w Jul 4, 2025
aebe186
fix: lint
ieow Jul 4, 2025
82f7597
fix: clear tooManyAttemptError on timeout
ieow Jul 8, 2025
dc1043e
fix: account status page
ieow Jul 8, 2025
2a454c0
Merge branch 'main' into feat/seedless-oauth-flow
chaitanyapotti Jul 8, 2025
9f8ae3d
fix: account status copywriting
ieow Jul 8, 2025
f520d41
fix: update snapshot
ieow Jul 8, 2025
5a118d7
fix: update snapshot
ieow Jul 8, 2025
833ecd7
feat: update snapshot
ieow Jul 8, 2025
6839615
fix: update snapshot
ieow Jul 8, 2025
e2b17b3
Merge branch 'feat/seedless-oauth-flow' into feat/seedless-change-pw
ieow Jul 8, 2025
5409403
fix: throw error after vault is properly restored
ieow Jul 8, 2025
86982e5
fix: remove redundance renderswitch
ieow Jul 8, 2025
d4dfcc9
fix: remove unreachable code
ieow Jul 8, 2025
984a38a
Merge branch 'main' into feat/seedless-oauth-flow
chaitanyapotti Jul 8, 2025
ce826fd
fix: flow break on create wallet
ieow Jul 8, 2025
64d8410
fix: address comment 2.3
ieow Jul 8, 2025
b416681
fix: address comment 2.3
ieow Jul 8, 2025
ad7721f
fix: address comment- remove any
ieow Jul 8, 2025
79a251f
Merge branch 'main' into feat/seedless-oauth-flow
hieu-w Jul 8, 2025
87c1d90
Merge branch 'feat/seedless-oauth-flow' into feat/seedless-change-pw
ieow Jul 8, 2025
e6481ae
Merge branch 'main' into feat/seedless-change-pw
ieow Jul 9, 2025
c6a231c
fix: testcases
ieow Jul 9, 2025
861692b
fix: checkdiff
ieow Jul 9, 2025
8fb4642
fix: update snapshot
ieow Jul 9, 2025
3c4cbc5
feat: update snapshot
ieow Jul 9, 2025
9603886
fix: update snapshot
ieow Jul 9, 2025
dc96331
fix: check diff
ieow Jul 9, 2025
d3c9af8
fix: address comment
ieow Jul 9, 2025
e31890e
feat: integrate Sentry error tracking across authentication views
huggingbot Jul 14, 2025
fcde1a7
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 14, 2025
68bdfd2
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 18, 2025
0d8890f
fix: Prettier
huggingbot Jul 18, 2025
cfa8e2e
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 18, 2025
85b0a05
fix: Lint
huggingbot Jul 18, 2025
e69a182
Merge branch 'feat/sentry-error-integration' of https://github.com/Me…
huggingbot Jul 18, 2025
e197047
refactor: Update test descriptions to clarify ErrorBoundary behavior …
huggingbot Jul 18, 2025
262b65a
fix: Prettier
huggingbot Jul 18, 2025
0c97462
Merge branch 'main' into feat/sentry-error-integration
hieu-w Jul 18, 2025
388e3f5
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 20, 2025
75bbef7
fix: Sentry Erro UI Update
smgv Jul 21, 2025
be064d9
fix: Cursor bot comment
huggingbot Jul 21, 2025
e3b4b5f
fix: snapshot update
smgv Jul 21, 2025
3c950d7
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 21, 2025
5ac030e
fix: Format
huggingbot Jul 21, 2025
ab03e3a
fix: Await setupSentry in captureExceptionForced function to ensure p…
huggingbot Jul 22, 2025
d7d0f5e
Merge branch 'main' into feat/sentry-error-integration
chaitanyapotti Jul 22, 2025
fdcf433
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 23, 2025
ffc7911
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 23, 2025
0a08886
fix: reset Sentry state after forced exception capture
huggingbot Jul 23, 2025
2beb973
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 23, 2025
782ad11
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 23, 2025
b4b6de5
fix: Tests
huggingbot Jul 23, 2025
8ada7bc
fix: Lint
huggingbot Jul 23, 2025
4e79cc1
Merge branch 'main' into feat/sentry-error-integration
huggingbot Jul 23, 2025
37657bc
Merge branch 'main' into feat/sentry-error-integration
hieu-w Jul 23, 2025
29b6f9e
fix: resolve confilct
hieu-w Jul 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion app/components/Views/ChoosePassword/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Platform,
} from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import { captureException } from '@sentry/react-native';
import Text, {
TextColor,
TextVariant,
Expand Down Expand Up @@ -75,6 +76,7 @@ import Routes from '../../../constants/navigation/Routes';
import { withMetricsAwareness } from '../../hooks/useMetrics';
import fox from '../../../animations/Searching_Fox.json';
import LottieView from 'lottie-react-native';
import ErrorBoundary from '../ErrorBoundary';
import {
TraceName,
endTrace,
Expand Down Expand Up @@ -248,6 +250,7 @@ class ChoosePassword extends PureComponent {
rememberMe: false,
loading: false,
error: null,
errorToThrow: null,
inputWidth: { width: '99%' },
showPasswordIndex: [0, 1],
passwordInputContainerFocusedIndex: -1,
Expand Down Expand Up @@ -369,6 +372,34 @@ class ChoosePassword extends PureComponent {
}
}

isOAuthPasswordCreationError = (error, authType) =>
authType.oauth2Login &&
error.message &&
error.message.includes('SeedlessOnboardingController');

handleOAuthPasswordCreationError = (error, authType) => {
// If user has already consented to analytics, report error using regular Sentry
if (this.props.metrics.isEnabled()) {
authType.oauth2Login &&
captureException(error, {
tags: {
view: 'ChoosePassword',
context:
'OAuth password creation failed - user consented to analytics',
},
});
} else {
// User hasn't consented to analytics yet, use ErrorBoundary onboarding flow
authType.oauth2Login &&
this.setState({
loading: false,
errorToThrow: new Error(
`OAuth password creation failed: ${error.message}`,
),
});
}
};

setSelection = () => {
const { isSelected } = this.state;
this.setState(() => ({ isSelected: !isSelected }));
Expand Down Expand Up @@ -429,6 +460,10 @@ class ChoosePassword extends PureComponent {
try {
await Authentication.newWalletAndKeychain(password, authType);
} catch (error) {
if (this.isOAuthPasswordCreationError(error, authType)) {
this.handleOAuthPasswordCreationError(error, authType);
return;
}
if (Device.isIos) {
await this.handleRejectedOsBiometricPrompt();
}
Expand Down Expand Up @@ -544,6 +579,10 @@ class ChoosePassword extends PureComponent {
newAuthData,
);
} catch (err) {
if (this.isOAuthPasswordCreationError(err, newAuthData)) {
this.handleOAuthPasswordCreationError(err, newAuthData);
return;
}
throw Error(strings('choose_password.disable_biometric_error'));
}
this.setState({
Expand Down Expand Up @@ -700,7 +739,7 @@ class ChoosePassword extends PureComponent {
);
};

render() {
renderContent = () => {
const { isSelected, password, passwordStrength, confirmPassword, loading } =
this.state;
const passwordsMatch = password !== '' && password === confirmPassword;
Expand Down Expand Up @@ -954,6 +993,31 @@ class ChoosePassword extends PureComponent {
)}
</SafeAreaView>
);
};

render() {
const { errorToThrow } = this.state;

// Component that throws error if needed (to be caught by ErrorBoundary)
const ThrowErrorIfNeeded = () => {
if (errorToThrow) {
throw errorToThrow;
}
return null;
};

return (
<ErrorBoundary
navigation={this.props.navigation}
view="ChoosePassword"
useOnboardingErrorHandling={
!!errorToThrow && !this.props.metrics.isEnabled()
}
>
<ThrowErrorIfNeeded />
{this.renderContent()}
</ErrorBoundary>
);
}
}

Expand Down
139 changes: 139 additions & 0 deletions app/components/Views/ChoosePassword/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { BIOMETRY_TYPE } from 'react-native-keychain';
import { Authentication } from '../../../core';
import { InteractionManager, Alert } from 'react-native';
import { EVENT_NAME } from '../../../core/Analytics';
import Logger from '../../../util/Logger';

jest.mock('../../../util/metrics/TrackOnboarding/trackOnboarding');

Expand Down Expand Up @@ -90,9 +91,11 @@ jest.mock('react-native/Libraries/Alert/Alert', () => ({
}));

const mockMetricsIsEnabled = jest.fn().mockReturnValue(true);
const mockTrackEvent = jest.fn();
jest.mock('../../../core/Analytics/MetaMetrics', () => ({
getInstance: () => ({
isEnabled: mockMetricsIsEnabled,
trackEvent: mockTrackEvent,
}),
}));

Expand Down Expand Up @@ -873,6 +876,142 @@ describe('ChoosePassword', () => {
mockNewWalletAndKeychain.mockRestore();
});

describe('ErrorBoundary Tests', () => {
it('should trigger ErrorBoundary for OAuth password creation failures when analytics disabled', async () => {
const loggerErrorSpy = jest.spyOn(Logger, 'error');
mockMetricsIsEnabled.mockReturnValueOnce(false);
const mockNewWalletAndKeychain = jest.spyOn(
Authentication,
'newWalletAndKeychain',
);
mockNewWalletAndKeychain
.mockRejectedValueOnce(
new Error('SeedlessOnboardingController - Auth server is down'),
)
.mockResolvedValueOnce(undefined);

const props: ChoosePasswordProps = {
...defaultProps,
route: {
...defaultProps.route,
params: {
...defaultProps.route.params,
[PREVIOUS_SCREEN]: ONBOARDING,
oauthLoginSuccess: true,
},
},
};
const component = renderWithProviders(<ChoosePassword {...props} />);

await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 100));
});

const passwordInput = component.getByTestId(
ChoosePasswordSelectorsIDs.NEW_PASSWORD_INPUT_ID,
);
const confirmPasswordInput = component.getByTestId(
ChoosePasswordSelectorsIDs.CONFIRM_PASSWORD_INPUT_ID,
);
const checkbox = component.getByTestId(
ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID,
);

await act(async () => {
fireEvent.press(checkbox);
fireEvent.changeText(passwordInput, 'StrongPassword123!');
});
await act(async () => {
fireEvent.changeText(confirmPasswordInput, 'StrongPassword123!');
});
await act(async () => {
fireEvent(confirmPasswordInput, 'submitEditing');
});

expect(mockNewWalletAndKeychain).toHaveBeenCalledTimes(1);
expect(loggerErrorSpy).toHaveBeenCalledWith(
expect.objectContaining({
message: expect.stringContaining('OAuth password creation failed'),
}),
expect.objectContaining({
View: 'ChoosePassword',
ErrorBoundary: true,
}),
);
expect(mockTrackEvent).toHaveBeenLastCalledWith(
expect.objectContaining({
name: 'Error Screen Viewed',
}),
);

mockNewWalletAndKeychain.mockRestore();
});

it('should not trigger ErrorBoundary for OAuth password creation failures when analytics enabled', async () => {
mockMetricsIsEnabled.mockReturnValueOnce(true);
const mockNewWalletAndKeychain = jest.spyOn(
Authentication,
'newWalletAndKeychain',
);
mockNewWalletAndKeychain
.mockRejectedValueOnce(
new Error('SeedlessOnboardingController - Auth server is down'),
)
.mockResolvedValueOnce(undefined);

const props: ChoosePasswordProps = {
...defaultProps,
route: {
...defaultProps.route,
params: {
...defaultProps.route.params,
[PREVIOUS_SCREEN]: ONBOARDING,
oauthLoginSuccess: true,
},
},
};
const component = renderWithProviders(<ChoosePassword {...props} />);

await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 100));
});

const passwordInput = component.getByTestId(
ChoosePasswordSelectorsIDs.NEW_PASSWORD_INPUT_ID,
);
const confirmPasswordInput = component.getByTestId(
ChoosePasswordSelectorsIDs.CONFIRM_PASSWORD_INPUT_ID,
);
const checkbox = component.getByTestId(
ChoosePasswordSelectorsIDs.I_UNDERSTAND_CHECKBOX_ID,
);

await act(async () => {
fireEvent.press(checkbox);
fireEvent.changeText(passwordInput, 'StrongPassword123!');
});
await act(async () => {
fireEvent.changeText(confirmPasswordInput, 'StrongPassword123!');
});
await act(async () => {
fireEvent(confirmPasswordInput, 'submitEditing');
});

await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 200));
});

expect(mockNewWalletAndKeychain).toHaveBeenCalledTimes(1);
expect(mockTrackEvent).not.toHaveBeenLastCalledWith(
expect.objectContaining({
name: 'Error Screen Viewed',
}),
);

mockNewWalletAndKeychain.mockRestore();
});
});

describe('Tracing functionality', () => {
const mockTrace = trace as jest.MockedFunction<typeof trace>;
const mockEndTrace = endTrace as jest.MockedFunction<typeof endTrace>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ErrorBoundary Onboarding Error Handling renders onboarding error state snapshot 1`] = `null`;

exports[`ErrorBoundary render matches snapshot 1`] = `null`;
Loading
Loading