From 9a33677e22eea3573f972934d44308a78ec032a8 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 9 Sep 2025 12:22:30 +0200 Subject: [PATCH 01/10] add metadata properties to `SubscriptionController` --- .../src/SubscriptionController.test.ts | 64 ++++++++++++++++++- .../src/SubscriptionController.ts | 2 + 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/packages/subscription-controller/src/SubscriptionController.test.ts b/packages/subscription-controller/src/SubscriptionController.test.ts index feca9b5c8e2..49655b76af9 100644 --- a/packages/subscription-controller/src/SubscriptionController.test.ts +++ b/packages/subscription-controller/src/SubscriptionController.test.ts @@ -1,4 +1,4 @@ -import { Messenger } from '@metamask/base-controller'; +import { deriveStateFromMetadata, Messenger } from '@metamask/base-controller'; import { controllerName, @@ -819,4 +819,66 @@ describe('SubscriptionController', () => { }); }); }); + + describe('metadata', () => { + it('includes expected state in debug snapshots', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'anonymous', + ), + ).toMatchInlineSnapshot(`Object {}`); + }); + }); + + it('includes expected state in state logs', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'includeInStateLogs', + ), + ).toMatchInlineSnapshot(` + Object { + "subscriptions": Array [], + } + `); + }); + }); + + it('persists expected state', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'persist', + ), + ).toMatchInlineSnapshot(` + Object { + "subscriptions": Array [], + } + `); + }); + }); + + it('exposes expected state to UI', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'usedInUi', + ), + ).toMatchInlineSnapshot(` + Object { + "subscriptions": Array [], + } + `); + }); + }); + }); }); diff --git a/packages/subscription-controller/src/SubscriptionController.ts b/packages/subscription-controller/src/SubscriptionController.ts index 6853f380e93..bbc5d0a6cef 100644 --- a/packages/subscription-controller/src/SubscriptionController.ts +++ b/packages/subscription-controller/src/SubscriptionController.ts @@ -133,8 +133,10 @@ export function getDefaultSubscriptionControllerState(): SubscriptionControllerS const subscriptionControllerMetadata: StateMetadata = { subscriptions: { + includeInStateLogs: true, persist: true, anonymous: false, + usedInUi: true, }, }; From 16432b91ba7e2002ee6190da7159aca7d397d1c2 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 9 Sep 2025 12:41:27 +0200 Subject: [PATCH 02/10] add metadata properties to `ShieldController` --- .../src/ShieldController.test.ts | 65 +++++++++++++++++++ .../shield-controller/src/ShieldController.ts | 4 ++ 2 files changed, 69 insertions(+) diff --git a/packages/shield-controller/src/ShieldController.test.ts b/packages/shield-controller/src/ShieldController.test.ts index 760f6a208a6..99c48de3d2c 100644 --- a/packages/shield-controller/src/ShieldController.test.ts +++ b/packages/shield-controller/src/ShieldController.test.ts @@ -1,3 +1,4 @@ +import { deriveStateFromMetadata } from '@metamask/base-controller'; import type { TransactionControllerState } from '@metamask/transaction-controller'; import { ShieldController } from './ShieldController'; @@ -142,4 +143,68 @@ describe('ShieldController', () => { expect(backend.checkCoverage).toHaveBeenCalledWith(txMeta); }); }); + + describe('metadata', () => { + it('includes expected state in debug snapshots', () => { + const { controller } = setup(); + + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'anonymous', + ), + ).toMatchInlineSnapshot(`Object {}`); + }); + + it('includes expected state in state logs', async () => { + const { controller } = setup(); + + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'includeInStateLogs', + ), + ).toMatchInlineSnapshot(` + Object { + "coverageResults": Object {}, + "orderedTransactionHistory": Array [], + } + `); + }); + + it('persists expected state', async () => { + const { controller } = setup(); + + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'persist', + ), + ).toMatchInlineSnapshot(` + Object { + "coverageResults": Object {}, + "orderedTransactionHistory": Array [], + } + `); + }); + + it('exposes expected state to UI', async () => { + const { controller } = setup(); + + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'usedInUi', + ), + ).toMatchInlineSnapshot(` + Object { + "coverageResults": Object {}, + } + `); + }); + }); }); diff --git a/packages/shield-controller/src/ShieldController.ts b/packages/shield-controller/src/ShieldController.ts index bbfb790ea61..af642ab9962 100644 --- a/packages/shield-controller/src/ShieldController.ts +++ b/packages/shield-controller/src/ShieldController.ts @@ -101,12 +101,16 @@ export type ShieldControllerMessenger = RestrictedMessenger< */ const metadata = { coverageResults: { + includeInStateLogs: true, persist: true, anonymous: false, + usedInUi: true, }, orderedTransactionHistory: { + includeInStateLogs: true, persist: true, anonymous: false, + usedInUi: false, }, }; From 0d338d23da4f48284a75f487614d6cebd0936fac Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 9 Sep 2025 14:03:09 +0200 Subject: [PATCH 03/10] add metadata properties to `SeedlessOnboardingController` --- .../CHANGELOG.md | 4 + .../src/SeedlessOnboardingController.test.ts | 222 +++++++++++++++++- .../src/SeedlessOnboardingController.ts | 46 +++- 3 files changed, 270 insertions(+), 2 deletions(-) diff --git a/packages/seedless-onboarding-controller/CHANGELOG.md b/packages/seedless-onboarding-controller/CHANGELOG.md index 8fabfcf2ae6..9e13c5a3275 100644 --- a/packages/seedless-onboarding-controller/CHANGELOG.md +++ b/packages/seedless-onboarding-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6504](https://github.com/MetaMask/core/pull/6504)) + ## [4.0.0] ### Added diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index 5cd8662d01b..f1912433dbb 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -1,5 +1,8 @@ import { keccak256AndHexify } from '@metamask/auth-network-utils'; -import type { Messenger } from '@metamask/base-controller'; +import { + deriveStateFromMetadata, + type Messenger, +} from '@metamask/base-controller'; import type { EncryptionKey } from '@metamask/browser-passworder'; import { encrypt, @@ -5432,4 +5435,221 @@ describe('SeedlessOnboardingController', () => { ); }); }); + + describe('metadata', () => { + it('includes expected state in debug snapshots', async () => { + await withController( + { + state: { + accessToken: 'accessToken', + authPubKey: 'authPubKey', + authConnection: AuthConnection.Google, + authConnectionId: 'authConnectionId', + encryptedKeyringEncryptionKey: 'encryptedKeyringEncryptionKey', + encryptedSeedlessEncryptionKey: 'encryptedSeedlessEncryptionKey', + groupedAuthConnectionId: 'groupedAuthConnectionId', + isSeedlessOnboardingUserAuthenticated: true, + metadataAccessToken: 'metadataAccessToken', + nodeAuthTokens: [], + passwordOutdatedCache: { + isExpiredPwd: false, + timestamp: 1234567890, + }, + refreshToken: 'refreshToken', + revokeToken: 'revokeToken', + socialBackupsMetadata: [], + socialLoginEmail: 'socialLoginEmail', + userId: 'userId', + vault: 'vault', + vaultEncryptionKey: 'vaultEncryptionKey', + vaultEncryptionSalt: 'vaultEncryptionSalt', + }, + }, + ({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'anonymous', + ), + ).toMatchInlineSnapshot(` + Object { + "authConnection": "google", + "authConnectionId": "authConnectionId", + "groupedAuthConnectionId": "groupedAuthConnectionId", + "isSeedlessOnboardingUserAuthenticated": false, + "passwordOutdatedCache": Object { + "isExpiredPwd": false, + "timestamp": 1234567890, + }, + } + `); + }, + ); + }); + + it('includes expected state in state logs', async () => { + await withController( + { + state: { + accessToken: 'accessToken', + authPubKey: 'authPubKey', + authConnection: AuthConnection.Google, + authConnectionId: 'authConnectionId', + encryptedKeyringEncryptionKey: 'encryptedKeyringEncryptionKey', + encryptedSeedlessEncryptionKey: 'encryptedSeedlessEncryptionKey', + groupedAuthConnectionId: 'groupedAuthConnectionId', + isSeedlessOnboardingUserAuthenticated: true, + metadataAccessToken: 'metadataAccessToken', + nodeAuthTokens: [], + passwordOutdatedCache: { + isExpiredPwd: false, + timestamp: 1234567890, + }, + refreshToken: 'refreshToken', + revokeToken: 'revokeToken', + socialBackupsMetadata: [], + socialLoginEmail: 'socialLoginEmail', + userId: 'userId', + vault: 'vault', + vaultEncryptionKey: 'vaultEncryptionKey', + vaultEncryptionSalt: 'vaultEncryptionSalt', + }, + }, + ({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'includeInStateLogs', + ), + ).toMatchInlineSnapshot(` + Object { + "accessToken": true, + "authConnection": "google", + "authConnectionId": "authConnectionId", + "authPubKey": "authPubKey", + "groupedAuthConnectionId": "groupedAuthConnectionId", + "isSeedlessOnboardingUserAuthenticated": false, + "metadataAccessToken": true, + "nodeAuthTokens": true, + "passwordOutdatedCache": Object { + "isExpiredPwd": false, + "timestamp": 1234567890, + }, + "refreshToken": true, + "revokeToken": true, + "userId": "userId", + } + `); + }, + ); + }); + + it('persists expected state', async () => { + await withController( + { + state: { + accessToken: 'accessToken', + authPubKey: 'authPubKey', + authConnection: AuthConnection.Google, + authConnectionId: 'authConnectionId', + encryptedKeyringEncryptionKey: 'encryptedKeyringEncryptionKey', + encryptedSeedlessEncryptionKey: 'encryptedSeedlessEncryptionKey', + groupedAuthConnectionId: 'groupedAuthConnectionId', + isSeedlessOnboardingUserAuthenticated: true, + metadataAccessToken: 'metadataAccessToken', + nodeAuthTokens: [], + passwordOutdatedCache: { + isExpiredPwd: false, + timestamp: 1234567890, + }, + refreshToken: 'refreshToken', + revokeToken: 'revokeToken', + socialBackupsMetadata: [], + socialLoginEmail: 'socialLoginEmail', + userId: 'userId', + vault: 'vault', + vaultEncryptionKey: 'vaultEncryptionKey', + vaultEncryptionSalt: 'vaultEncryptionSalt', + }, + }, + ({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'persist', + ), + ).toMatchInlineSnapshot(` + Object { + "authConnection": "google", + "authConnectionId": "authConnectionId", + "authPubKey": "authPubKey", + "encryptedKeyringEncryptionKey": "encryptedKeyringEncryptionKey", + "encryptedSeedlessEncryptionKey": "encryptedSeedlessEncryptionKey", + "groupedAuthConnectionId": "groupedAuthConnectionId", + "isSeedlessOnboardingUserAuthenticated": false, + "metadataAccessToken": "metadataAccessToken", + "nodeAuthTokens": Array [], + "passwordOutdatedCache": Object { + "isExpiredPwd": false, + "timestamp": 1234567890, + }, + "refreshToken": "refreshToken", + "socialBackupsMetadata": Array [], + "socialLoginEmail": "socialLoginEmail", + "userId": "userId", + "vault": "vault", + } + `); + }, + ); + }); + + it('exposes expected state to UI', async () => { + await withController( + { + state: { + accessToken: 'accessToken', + authPubKey: 'authPubKey', + authConnection: AuthConnection.Google, + authConnectionId: 'authConnectionId', + encryptedKeyringEncryptionKey: 'encryptedKeyringEncryptionKey', + encryptedSeedlessEncryptionKey: 'encryptedSeedlessEncryptionKey', + groupedAuthConnectionId: 'groupedAuthConnectionId', + isSeedlessOnboardingUserAuthenticated: true, + metadataAccessToken: 'metadataAccessToken', + nodeAuthTokens: [], + passwordOutdatedCache: { + isExpiredPwd: false, + timestamp: 1234567890, + }, + refreshToken: 'refreshToken', + revokeToken: 'revokeToken', + socialBackupsMetadata: [], + socialLoginEmail: 'socialLoginEmail', + userId: 'userId', + vault: 'vault', + vaultEncryptionKey: 'vaultEncryptionKey', + vaultEncryptionSalt: 'vaultEncryptionSalt', + }, + }, + ({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'usedInUi', + ), + ).toMatchInlineSnapshot(` + Object { + "authConnection": "google", + "socialLoginEmail": "socialLoginEmail", + } + `); + }, + ); + }); + }); }); diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index ce5cec7d0d6..ff4bd62f214 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -11,7 +11,11 @@ import { TOPRFErrorCode, TOPRFError, } from '@metamask/toprf-secure-backup'; -import { base64ToBytes, bytesToBase64 } from '@metamask/utils'; +import { + base64ToBytes, + bytesToBase64, + isNullOrUndefined, +} from '@metamask/utils'; import { gcm } from '@noble/ciphers/aes'; import { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils'; import { managedNonce } from '@noble/ciphers/webcrypto'; @@ -93,60 +97,89 @@ export function getInitialSeedlessOnboardingControllerStateWithDefaults( const seedlessOnboardingMetadata: StateMetadata = { vault: { + includeInStateLogs: false, persist: true, anonymous: false, + usedInUi: false, }, socialBackupsMetadata: { + includeInStateLogs: false, persist: true, anonymous: false, + usedInUi: false, }, nodeAuthTokens: { + includeInStateLogs: (nodeAuthTokens) => + !isNullOrUndefined(nodeAuthTokens), persist: true, anonymous: false, + usedInUi: false, }, authConnection: { + includeInStateLogs: true, persist: true, anonymous: true, + usedInUi: true, }, authConnectionId: { + includeInStateLogs: true, persist: true, anonymous: true, + usedInUi: false, }, groupedAuthConnectionId: { + includeInStateLogs: true, persist: true, anonymous: true, + usedInUi: false, }, userId: { + includeInStateLogs: true, persist: true, anonymous: false, + usedInUi: false, }, socialLoginEmail: { + includeInStateLogs: false, persist: true, anonymous: false, + usedInUi: true, }, vaultEncryptionKey: { + includeInStateLogs: false, persist: false, anonymous: false, + usedInUi: false, }, vaultEncryptionSalt: { + includeInStateLogs: false, persist: false, anonymous: false, + usedInUi: false, }, authPubKey: { + includeInStateLogs: true, persist: true, anonymous: false, + usedInUi: false, }, passwordOutdatedCache: { + includeInStateLogs: true, persist: true, anonymous: true, + usedInUi: false, }, refreshToken: { + includeInStateLogs: (refreshToken) => !isNullOrUndefined(refreshToken), persist: true, anonymous: false, + usedInUi: false, }, revokeToken: { + includeInStateLogs: (revokeToken) => !isNullOrUndefined(revokeToken), persist: false, anonymous: false, + usedInUi: false, }, pendingToBeRevokedTokens: { persist: true, @@ -154,26 +187,37 @@ const seedlessOnboardingMetadata: StateMetadata !isNullOrUndefined(accessToken), persist: false, anonymous: false, + usedInUi: false, }, // stays outside of vault as this token is accessed by the metadata service // before the vault is created or unlocked. metadataAccessToken: { + includeInStateLogs: (metadataAccessToken) => + !isNullOrUndefined(metadataAccessToken), persist: true, anonymous: false, + usedInUi: false, }, encryptedSeedlessEncryptionKey: { + includeInStateLogs: false, persist: true, anonymous: false, + usedInUi: false, }, encryptedKeyringEncryptionKey: { + includeInStateLogs: false, persist: true, anonymous: false, + usedInUi: false, }, isSeedlessOnboardingUserAuthenticated: { + includeInStateLogs: true, persist: true, anonymous: true, + usedInUi: false, }, }; From 6377abdba6b14b1163b8418ebed5a24dc61defb0 Mon Sep 17 00:00:00 2001 From: Michele Esposito Date: Tue, 9 Sep 2025 14:03:48 +0200 Subject: [PATCH 04/10] update changelogs --- packages/shield-controller/CHANGELOG.md | 4 ++++ packages/subscription-controller/CHANGELOG.md | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/shield-controller/CHANGELOG.md b/packages/shield-controller/CHANGELOG.md index bb9d5311d67..f0ec19a0273 100644 --- a/packages/shield-controller/CHANGELOG.md +++ b/packages/shield-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6504](https://github.com/MetaMask/core/pull/6504)) + ### Changed - Bump `@metamask/base-controller` from `^8.2.0` to `^8.3.0` ([#6465](https://github.com/MetaMask/core/pull/6465)) diff --git a/packages/subscription-controller/CHANGELOG.md b/packages/subscription-controller/CHANGELOG.md index fc4fb2f3eea..d1cc723a00f 100644 --- a/packages/subscription-controller/CHANGELOG.md +++ b/packages/subscription-controller/CHANGELOG.md @@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `cancelSubscription`: Cancel user active subscription. - `startShieldSubscriptionWithCard`: start shield subscription via card (with trial option) ([#6300](https://github.com/MetaMask/core/pull/6300)) - Add `getPricing` method ([#6356](https://github.com/MetaMask/core/pull/6356)) -- Add methods `startSubscriptionWithCrypto` and `getCryptoApproveTransactionParams` method ([#6456](https://github.com/MetaMask/core/pull/6456)) - Added `triggerAccessTokenRefresh` to trigger an access token refresh ([#6374](https://github.com/MetaMask/core/pull/6374)) +- Add methods `startSubscriptionWithCrypto` and `getCryptoApproveTransactionParams` method ([#6456](https://github.com/MetaMask/core/pull/6456)) +- Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6504](https://github.com/MetaMask/core/pull/6504)) [Unreleased]: https://github.com/MetaMask/core/ From 365d2079356be2ab56ce76b1c03864c4a2ca8d39 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 9 Sep 2025 16:30:42 +0200 Subject: [PATCH 05/10] update `includeInStateLogs` properties in `SeedlessOnboardingController` --- .../src/SeedlessOnboardingController.test.ts | 5 ----- .../src/SeedlessOnboardingController.ts | 14 +++++++------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index f1912433dbb..117fc4b2580 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -5525,20 +5525,15 @@ describe('SeedlessOnboardingController', () => { ), ).toMatchInlineSnapshot(` Object { - "accessToken": true, "authConnection": "google", "authConnectionId": "authConnectionId", "authPubKey": "authPubKey", "groupedAuthConnectionId": "groupedAuthConnectionId", "isSeedlessOnboardingUserAuthenticated": false, - "metadataAccessToken": true, - "nodeAuthTokens": true, "passwordOutdatedCache": Object { "isExpiredPwd": false, "timestamp": 1234567890, }, - "refreshToken": true, - "revokeToken": true, "userId": "userId", } `); diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index ff4bd62f214..7ac00d119a6 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -109,8 +109,7 @@ const seedlessOnboardingMetadata: StateMetadata - !isNullOrUndefined(nodeAuthTokens), + includeInStateLogs: false, persist: true, anonymous: false, usedInUi: false, @@ -170,24 +169,26 @@ const seedlessOnboardingMetadata: StateMetadata !isNullOrUndefined(refreshToken), + includeInStateLogs: false, persist: true, anonymous: false, usedInUi: false, }, revokeToken: { - includeInStateLogs: (revokeToken) => !isNullOrUndefined(revokeToken), + includeInStateLogs: false, persist: false, anonymous: false, usedInUi: false, }, pendingToBeRevokedTokens: { + includeInStateLogs: false, persist: true, anonymous: false, + usedInUi: false, }, // stays in vault accessToken: { - includeInStateLogs: (accessToken) => !isNullOrUndefined(accessToken), + includeInStateLogs: false, persist: false, anonymous: false, usedInUi: false, @@ -195,8 +196,7 @@ const seedlessOnboardingMetadata: StateMetadata - !isNullOrUndefined(metadataAccessToken), + includeInStateLogs: false, persist: true, anonymous: false, usedInUi: false, From 1aae447890579718452c7c10a919594c32fb46d5 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 9 Sep 2025 16:31:49 +0200 Subject: [PATCH 06/10] revert CHANGELOG update --- packages/subscription-controller/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/subscription-controller/CHANGELOG.md b/packages/subscription-controller/CHANGELOG.md index d1cc723a00f..b7483921596 100644 --- a/packages/subscription-controller/CHANGELOG.md +++ b/packages/subscription-controller/CHANGELOG.md @@ -14,8 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `cancelSubscription`: Cancel user active subscription. - `startShieldSubscriptionWithCard`: start shield subscription via card (with trial option) ([#6300](https://github.com/MetaMask/core/pull/6300)) - Add `getPricing` method ([#6356](https://github.com/MetaMask/core/pull/6356)) -- Added `triggerAccessTokenRefresh` to trigger an access token refresh ([#6374](https://github.com/MetaMask/core/pull/6374)) - Add methods `startSubscriptionWithCrypto` and `getCryptoApproveTransactionParams` method ([#6456](https://github.com/MetaMask/core/pull/6456)) +- Added `triggerAccessTokenRefresh` to trigger an access token refresh ([#6374](https://github.com/MetaMask/core/pull/6374)) - Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6504](https://github.com/MetaMask/core/pull/6504)) [Unreleased]: https://github.com/MetaMask/core/ From ecd6a859c12fe82e0b2971c4be26a9a5afa3c867 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 9 Sep 2025 16:32:53 +0200 Subject: [PATCH 07/10] remove unused import --- .../src/SeedlessOnboardingController.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index 7ac00d119a6..c3c506350e2 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -11,11 +11,7 @@ import { TOPRFErrorCode, TOPRFError, } from '@metamask/toprf-secure-backup'; -import { - base64ToBytes, - bytesToBase64, - isNullOrUndefined, -} from '@metamask/utils'; +import { base64ToBytes, bytesToBase64 } from '@metamask/utils'; import { gcm } from '@noble/ciphers/aes'; import { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils'; import { managedNonce } from '@noble/ciphers/webcrypto'; From 38bd6b57d5723c600a1f31e3314b39b62dd3f9e7 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 10 Sep 2025 11:34:04 +0200 Subject: [PATCH 08/10] Revert "update `includeInStateLogs` properties in `SeedlessOnboardingController`" This reverts commit f8b67c448c2d064e03e61b53474b1a23c56cb18e. --- .../src/SeedlessOnboardingController.test.ts | 5 +++++ .../src/SeedlessOnboardingController.ts | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index 117fc4b2580..f1912433dbb 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -5525,15 +5525,20 @@ describe('SeedlessOnboardingController', () => { ), ).toMatchInlineSnapshot(` Object { + "accessToken": true, "authConnection": "google", "authConnectionId": "authConnectionId", "authPubKey": "authPubKey", "groupedAuthConnectionId": "groupedAuthConnectionId", "isSeedlessOnboardingUserAuthenticated": false, + "metadataAccessToken": true, + "nodeAuthTokens": true, "passwordOutdatedCache": Object { "isExpiredPwd": false, "timestamp": 1234567890, }, + "refreshToken": true, + "revokeToken": true, "userId": "userId", } `); diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index c3c506350e2..e6d1b86fa72 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -105,7 +105,8 @@ const seedlessOnboardingMetadata: StateMetadata + !isNullOrUndefined(nodeAuthTokens), persist: true, anonymous: false, usedInUi: false, @@ -165,26 +166,24 @@ const seedlessOnboardingMetadata: StateMetadata !isNullOrUndefined(refreshToken), persist: true, anonymous: false, usedInUi: false, }, revokeToken: { - includeInStateLogs: false, + includeInStateLogs: (revokeToken) => !isNullOrUndefined(revokeToken), persist: false, anonymous: false, usedInUi: false, }, pendingToBeRevokedTokens: { - includeInStateLogs: false, persist: true, anonymous: false, - usedInUi: false, }, // stays in vault accessToken: { - includeInStateLogs: false, + includeInStateLogs: (accessToken) => !isNullOrUndefined(accessToken), persist: false, anonymous: false, usedInUi: false, @@ -192,7 +191,8 @@ const seedlessOnboardingMetadata: StateMetadata + !isNullOrUndefined(metadataAccessToken), persist: true, anonymous: false, usedInUi: false, From 0c9559656a8c05070354e9433d822548af4dc25b Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 10 Sep 2025 11:46:57 +0200 Subject: [PATCH 09/10] update `pendingToBeRevokedTokens` metadata --- .../src/SeedlessOnboardingController.test.ts | 16 ++++++++++++++++ .../src/SeedlessOnboardingController.ts | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index f1912433dbb..7f8337732a4 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -5506,6 +5506,9 @@ describe('SeedlessOnboardingController', () => { isExpiredPwd: false, timestamp: 1234567890, }, + pendingToBeRevokedTokens: [ + { refreshToken: 'refreshToken', revokeToken: 'revokeToken' }, + ], refreshToken: 'refreshToken', revokeToken: 'revokeToken', socialBackupsMetadata: [], @@ -5537,6 +5540,7 @@ describe('SeedlessOnboardingController', () => { "isExpiredPwd": false, "timestamp": 1234567890, }, + "pendingToBeRevokedTokens": true, "refreshToken": true, "revokeToken": true, "userId": "userId", @@ -5564,6 +5568,9 @@ describe('SeedlessOnboardingController', () => { isExpiredPwd: false, timestamp: 1234567890, }, + pendingToBeRevokedTokens: [ + { refreshToken: 'refreshToken', revokeToken: 'revokeToken' }, + ], refreshToken: 'refreshToken', revokeToken: 'revokeToken', socialBackupsMetadata: [], @@ -5596,6 +5603,12 @@ describe('SeedlessOnboardingController', () => { "isExpiredPwd": false, "timestamp": 1234567890, }, + pendingToBeRevokedTokens: Array [ + Object { + "refreshToken": "refreshToken", + "revokeToken": "revokeToken" + }, + ], "refreshToken": "refreshToken", "socialBackupsMetadata": Array [], "socialLoginEmail": "socialLoginEmail", @@ -5625,6 +5638,9 @@ describe('SeedlessOnboardingController', () => { isExpiredPwd: false, timestamp: 1234567890, }, + pendingToBeRevokedTokens: [ + { refreshToken: 'refreshToken', revokeToken: 'revokeToken' }, + ], refreshToken: 'refreshToken', revokeToken: 'revokeToken', socialBackupsMetadata: [], diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index e6d1b86fa72..b06b377a956 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -11,7 +11,11 @@ import { TOPRFErrorCode, TOPRFError, } from '@metamask/toprf-secure-backup'; -import { base64ToBytes, bytesToBase64 } from '@metamask/utils'; +import { + base64ToBytes, + bytesToBase64, + isNullOrUndefined, +} from '@metamask/utils'; import { gcm } from '@noble/ciphers/aes'; import { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils'; import { managedNonce } from '@noble/ciphers/webcrypto'; @@ -178,8 +182,12 @@ const seedlessOnboardingMetadata: StateMetadata + !isNullOrUndefined(pendingToBeRevokedTokens) && + pendingToBeRevokedTokens.length > 0, persist: true, anonymous: false, + usedInUi: false, }, // stays in vault accessToken: { From e66248b7880ccae5c3dabd824915bfec134463cb Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 10 Sep 2025 11:51:56 +0200 Subject: [PATCH 10/10] update tests --- .../src/SeedlessOnboardingController.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index 7f8337732a4..d058088eb61 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -5455,6 +5455,9 @@ describe('SeedlessOnboardingController', () => { isExpiredPwd: false, timestamp: 1234567890, }, + pendingToBeRevokedTokens: [ + { refreshToken: 'refreshToken', revokeToken: 'revokeToken' }, + ], refreshToken: 'refreshToken', revokeToken: 'revokeToken', socialBackupsMetadata: [], @@ -5603,10 +5606,10 @@ describe('SeedlessOnboardingController', () => { "isExpiredPwd": false, "timestamp": 1234567890, }, - pendingToBeRevokedTokens: Array [ + "pendingToBeRevokedTokens": Array [ Object { "refreshToken": "refreshToken", - "revokeToken": "revokeToken" + "revokeToken": "revokeToken", }, ], "refreshToken": "refreshToken",