From df57986c6226bfe1406b07841f4f1b87ff597f8d Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 11 Nov 2025 13:21:22 +0800 Subject: [PATCH 1/6] chore: removed Content-Type from 'getRequestHeaders' method --- packages/claims-controller/src/ClaimService.test.ts | 4 ---- .../claims-controller/src/ClaimsController.test.ts | 11 ++--------- packages/claims-controller/src/ClaimsController.ts | 2 -- packages/claims-controller/src/ClaimsService.ts | 7 +------ packages/claims-controller/src/constants.ts | 5 ----- packages/claims-controller/tsconfig.json | 2 -- 6 files changed, 3 insertions(+), 28 deletions(-) diff --git a/packages/claims-controller/src/ClaimService.test.ts b/packages/claims-controller/src/ClaimService.test.ts index 0ce5b0c3af2..ed2b975fe0d 100644 --- a/packages/claims-controller/src/ClaimService.test.ts +++ b/packages/claims-controller/src/ClaimService.test.ts @@ -4,7 +4,6 @@ import { ClaimsServiceErrorMessages, ClaimStatusEnum, Env, - HttpContentTypeHeader, } from './constants'; import type { Claim, GenerateSignatureMessageResponse } from './types'; import { createMockClaimsServiceMessenger } from '../tests/mocks/messenger'; @@ -103,7 +102,6 @@ describe('ClaimsService', () => { { headers: { Authorization: 'Bearer test-token', - 'Content-Type': HttpContentTypeHeader.APPLICATION_JSON, }, }, ); @@ -154,7 +152,6 @@ describe('ClaimsService', () => { { headers: { Authorization: 'Bearer test-token', - 'Content-Type': HttpContentTypeHeader.APPLICATION_JSON, }, }, ); @@ -216,7 +213,6 @@ describe('ClaimsService', () => { { headers: { Authorization: 'Bearer test-token', - 'Content-Type': HttpContentTypeHeader.APPLICATION_JSON, }, method: 'POST', body: JSON.stringify({ diff --git a/packages/claims-controller/src/ClaimsController.test.ts b/packages/claims-controller/src/ClaimsController.test.ts index d92f5d4cbd2..561c52c18ba 100644 --- a/packages/claims-controller/src/ClaimsController.test.ts +++ b/packages/claims-controller/src/ClaimsController.test.ts @@ -1,9 +1,5 @@ import { ClaimsController } from './ClaimsController'; -import { - ClaimsControllerErrorMessages, - ClaimStatusEnum, - HttpContentTypeHeader, -} from './constants'; +import { ClaimsControllerErrorMessages, ClaimStatusEnum } from './constants'; import type { Claim, CreateClaimRequest } from './types'; import { createMockClaimsControllerMessenger } from '../tests/mocks/messenger'; import type { WithControllerArgs } from '../tests/types'; @@ -65,7 +61,6 @@ describe('ClaimsController', () => { }; const MOCK_CLAIM_API = 'https://claims-api.test.com'; const MOCK_HEADERS = { - 'Content-Type': HttpContentTypeHeader.MULTIPART_FORM_DATA, Authorization: 'Bearer test-token', }; @@ -81,9 +76,7 @@ describe('ClaimsController', () => { const submitClaimConfig = await controller.getSubmitClaimConfig(MOCK_CLAIM); - expect(mockClaimServiceRequestHeaders).toHaveBeenCalledWith( - HttpContentTypeHeader.MULTIPART_FORM_DATA, - ); + expect(mockClaimServiceRequestHeaders).toHaveBeenCalledTimes(1); expect(mockClaimServiceGetClaimsApiUrl).toHaveBeenCalledTimes(1); expect(submitClaimConfig).toBeDefined(); diff --git a/packages/claims-controller/src/ClaimsController.ts b/packages/claims-controller/src/ClaimsController.ts index 56700b8d77f..b8bb2d81a82 100644 --- a/packages/claims-controller/src/ClaimsController.ts +++ b/packages/claims-controller/src/ClaimsController.ts @@ -19,7 +19,6 @@ import type { import { ClaimsControllerErrorMessages, CONTROLLER_NAME, - HttpContentTypeHeader, SERVICE_NAME, } from './constants'; import type { @@ -109,7 +108,6 @@ export class ClaimsController extends BaseController< const headers = await this.messenger.call( `${SERVICE_NAME}:getRequestHeaders`, - HttpContentTypeHeader.MULTIPART_FORM_DATA, ); const baseUrl = this.messenger.call(`${SERVICE_NAME}:getClaimsApiUrl`); const url = `${baseUrl}/claims`; diff --git a/packages/claims-controller/src/ClaimsService.ts b/packages/claims-controller/src/ClaimsService.ts index 56feff68685..ed6dcf78326 100644 --- a/packages/claims-controller/src/ClaimsService.ts +++ b/packages/claims-controller/src/ClaimsService.ts @@ -6,7 +6,6 @@ import { CLAIMS_API_URL, ClaimsServiceErrorMessages, type Env, - HttpContentTypeHeader, SERVICE_NAME, } from './constants'; import type { Claim, GenerateSignatureMessageResponse } from './types'; @@ -171,18 +170,14 @@ export class ClaimsService { /** * Create the headers for the current request. * - * @param contentType - The content type of the request. Defaults to 'application/json'. * @returns The headers for the current request. */ - async getRequestHeaders( - contentType: HttpContentTypeHeader = HttpContentTypeHeader.APPLICATION_JSON, - ): Promise> { + async getRequestHeaders(): Promise> { const bearerToken = await this.#messenger.call( 'AuthenticationController:getBearerToken', ); return { Authorization: `Bearer ${bearerToken}`, - 'Content-Type': contentType, }; } diff --git a/packages/claims-controller/src/constants.ts b/packages/claims-controller/src/constants.ts index 22074db7213..e5fff384599 100644 --- a/packages/claims-controller/src/constants.ts +++ b/packages/claims-controller/src/constants.ts @@ -31,11 +31,6 @@ export const CLAIMS_API_URL: Record = { [Env.PRD]: 'https://claims.api.cx.metamask.io', }; -export enum HttpContentTypeHeader { - APPLICATION_JSON = 'application/json', - MULTIPART_FORM_DATA = 'multipart/form-data', -} - export const ClaimsControllerErrorMessages = { CLAIM_ALREADY_SUBMITTED: 'Claim already submitted', INVALID_CLAIM_SIGNATURE: 'Invalid claim signature', diff --git a/packages/claims-controller/tsconfig.json b/packages/claims-controller/tsconfig.json index 72f54050b98..51ec679d169 100644 --- a/packages/claims-controller/tsconfig.json +++ b/packages/claims-controller/tsconfig.json @@ -2,8 +2,6 @@ "extends": "../../tsconfig.packages.json", "compilerOptions": { "baseUrl": "./", - "outDir": "./dist", - "rootDir": "./src" }, "references": [ { From 98314cbd2c5dbb1c736e5281c2189a2fe83900a2 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 11 Nov 2025 13:55:25 +0800 Subject: [PATCH 2/6] feat: fetch claims configuration from backend --- .../src/ClaimsController.test.ts | 50 +++++++++++++- .../claims-controller/src/ClaimsController.ts | 44 +++++++++++- ...mService.test.ts => ClaimsService.test.ts} | 68 +++++++++++++++++-- .../claims-controller/src/ClaimsService.ts | 42 +++++++++++- packages/claims-controller/src/constants.ts | 16 ++++- packages/claims-controller/src/index.ts | 11 ++- packages/claims-controller/src/types.ts | 28 +++++++- .../tests/mocks/messenger.ts | 8 +++ 8 files changed, 254 insertions(+), 13 deletions(-) rename packages/claims-controller/src/{ClaimService.test.ts => ClaimsService.test.ts} (77%) diff --git a/packages/claims-controller/src/ClaimsController.test.ts b/packages/claims-controller/src/ClaimsController.test.ts index 561c52c18ba..571e7099cf8 100644 --- a/packages/claims-controller/src/ClaimsController.test.ts +++ b/packages/claims-controller/src/ClaimsController.test.ts @@ -1,6 +1,12 @@ +import { toHex } from '@metamask/controller-utils'; + import { ClaimsController } from './ClaimsController'; import { ClaimsControllerErrorMessages, ClaimStatusEnum } from './constants'; -import type { Claim, CreateClaimRequest } from './types'; +import type { + Claim, + ClaimsConfigurationsResponse, + CreateClaimRequest, +} from './types'; import { createMockClaimsControllerMessenger } from '../tests/mocks/messenger'; import type { WithControllerArgs } from '../tests/types'; @@ -9,6 +15,7 @@ const mockClaimServiceGetClaimsApiUrl = jest.fn(); const mockClaimServiceGenerateMessageForClaimSignature = jest.fn(); const mockKeyringControllerSignPersonalMessage = jest.fn(); const mockClaimsServiceGetClaims = jest.fn(); +const mockClaimsServiceFetchClaimsConfigurations = jest.fn(); /** * Builds a controller based on the given options and calls the given function with that controller. @@ -26,6 +33,7 @@ async function withController( mockClaimServiceGenerateMessageForClaimSignature, mockKeyringControllerSignPersonalMessage, mockClaimsServiceGetClaims, + mockClaimsServiceFetchClaimsConfigurations, }); const controller = new ClaimsController({ @@ -48,6 +56,46 @@ describe('ClaimsController', () => { }); }); + describe('fetchClaimsConfigurations', () => { + const MOCK_CONFIGURATIONS_RESPONSE: ClaimsConfigurationsResponse = { + validSubmissionWindowDays: 21, + networks: [1, 5, 11155111], + }; + + beforeEach(() => { + jest.resetAllMocks(); + + mockClaimsServiceFetchClaimsConfigurations.mockResolvedValueOnce( + MOCK_CONFIGURATIONS_RESPONSE, + ); + }); + + it('should fetch claims configurations successfully', async () => { + await withController(async ({ controller }) => { + const initialState = controller.state; + const configurations = await controller.fetchClaimsConfigurations(); + expect(configurations).toBeDefined(); + + const expectedConfigurations = { + validSubmissionWindowDays: + MOCK_CONFIGURATIONS_RESPONSE.validSubmissionWindowDays, + supportedNetworks: MOCK_CONFIGURATIONS_RESPONSE.networks.map( + (network) => toHex(network), + ), + }; + + expect(configurations).toStrictEqual(expectedConfigurations); + expect(controller.state).not.toBe(initialState); + expect(controller.state.validSubmissionWindowDays).toBe( + MOCK_CONFIGURATIONS_RESPONSE.validSubmissionWindowDays, + ); + expect(controller.state.supportedNetworks).toStrictEqual( + expectedConfigurations.supportedNetworks, + ); + }); + }); + }); + describe('getSubmitClaimConfig', () => { const MOCK_CLAIM: CreateClaimRequest = { chainId: '0x1', diff --git a/packages/claims-controller/src/ClaimsController.ts b/packages/claims-controller/src/ClaimsController.ts index b8bb2d81a82..2655fa500e9 100644 --- a/packages/claims-controller/src/ClaimsController.ts +++ b/packages/claims-controller/src/ClaimsController.ts @@ -4,12 +4,13 @@ import type { StateMetadata, } from '@metamask/base-controller'; import { BaseController } from '@metamask/base-controller'; -import { detectSIWE } from '@metamask/controller-utils'; +import { detectSIWE, toHex } from '@metamask/controller-utils'; import type { KeyringControllerSignPersonalMessageAction } from '@metamask/keyring-controller'; import type { Messenger } from '@metamask/messenger'; import { bytesToHex, stringToBytes } from '@metamask/utils'; import type { + ClaimsServiceFetchClaimsConfigurationsAction, ClaimsServiceGenerateMessageForClaimSignatureAction, ClaimsServiceGetClaimByIdAction, ClaimsServiceGetClaimsAction, @@ -19,10 +20,12 @@ import type { import { ClaimsControllerErrorMessages, CONTROLLER_NAME, + DEFAULT_CLAIMS_CONFIGURATIONS, SERVICE_NAME, } from './constants'; import type { Claim, + ClaimsConfigurations, ClaimsControllerState, CreateClaimRequest, SubmitClaimConfig, @@ -36,6 +39,7 @@ export type ClaimsControllerGetStateAction = ControllerGetStateAction< export type ClaimsControllerActions = ClaimsControllerGetStateAction; export type AllowedActions = + | ClaimsServiceFetchClaimsConfigurationsAction | ClaimsServiceGetClaimsAction | ClaimsServiceGetClaimByIdAction | ClaimsServiceGetRequestHeadersAction @@ -67,6 +71,18 @@ const ClaimsControllerStateMetadata: StateMetadata = { includeInDebugSnapshot: false, usedInUi: true, }, + validSubmissionWindowDays: { + includeInStateLogs: true, + persist: true, + includeInDebugSnapshot: true, + usedInUi: true, + }, + supportedNetworks: { + includeInStateLogs: true, + persist: true, + includeInDebugSnapshot: true, + usedInUi: true, + }, }; /** @@ -76,6 +92,7 @@ const ClaimsControllerStateMetadata: StateMetadata = { */ export function getDefaultClaimsControllerState(): ClaimsControllerState { return { + ...DEFAULT_CLAIMS_CONFIGURATIONS, claims: [], }; } @@ -94,6 +111,31 @@ export class ClaimsController extends BaseController< }); } + /** + * Fetch the required configurations for the claims service. + * + * @returns The required configurations for the claims service. + */ + async fetchClaimsConfigurations(): Promise { + const configurations = await this.messenger.call( + `${SERVICE_NAME}:fetchClaimsConfigurations`, + ); + + const supportedNetworks = configurations.networks.map((network) => + toHex(network), + ); + + this.update((state) => { + state.validSubmissionWindowDays = + configurations.validSubmissionWindowDays; + state.supportedNetworks = supportedNetworks; + }); + return { + validSubmissionWindowDays: configurations.validSubmissionWindowDays, + supportedNetworks, + }; + } + /** * Get required config for submitting a claim. * diff --git a/packages/claims-controller/src/ClaimService.test.ts b/packages/claims-controller/src/ClaimsService.test.ts similarity index 77% rename from packages/claims-controller/src/ClaimService.test.ts rename to packages/claims-controller/src/ClaimsService.test.ts index ed2b975fe0d..c6aa8a2c2ed 100644 --- a/packages/claims-controller/src/ClaimService.test.ts +++ b/packages/claims-controller/src/ClaimsService.test.ts @@ -1,11 +1,15 @@ import { ClaimsService } from './ClaimsService'; import { - CLAIMS_API_URL, + CLAIMS_API_URL_MAP, ClaimsServiceErrorMessages, ClaimStatusEnum, Env, } from './constants'; -import type { Claim, GenerateSignatureMessageResponse } from './types'; +import type { + Claim, + ClaimsConfigurationsResponse, + GenerateSignatureMessageResponse, +} from './types'; import { createMockClaimsServiceMessenger } from '../tests/mocks/messenger'; const mockAuthenticationControllerGetBearerToken = jest.fn(); @@ -75,6 +79,60 @@ describe('ClaimsService', () => { }); }); + describe('fetchClaimsConfigurations', () => { + const MOCK_CONFIGURATIONS: ClaimsConfigurationsResponse = { + validSubmissionWindowDays: 21, + networks: [1, 5, 11155111], + }; + + beforeEach(() => { + jest.resetAllMocks(); + + mockAuthenticationControllerGetBearerToken.mockResolvedValueOnce( + 'test-token', + ); + mockFetchFunction.mockResolvedValueOnce({ + ok: true, + json: jest.fn().mockResolvedValueOnce(MOCK_CONFIGURATIONS), + }); + }); + + it('should fetch claims configurations successfully', async () => { + const service = createMockClaimsService(); + + const configurations = await service.fetchClaimsConfigurations(); + + expect(mockAuthenticationControllerGetBearerToken).toHaveBeenCalledTimes( + 1, + ); + expect(mockFetchFunction).toHaveBeenCalledTimes(1); + expect(mockFetchFunction).toHaveBeenCalledWith( + `${CLAIMS_API_URL_MAP[Env.DEV]}/configurations`, + { + headers: { + Authorization: 'Bearer test-token', + }, + }, + ); + expect(configurations).toStrictEqual(MOCK_CONFIGURATIONS); + }); + + it('should throw error if fetch fails', async () => { + mockFetchFunction.mockRestore(); + + mockFetchFunction.mockResolvedValueOnce({ + ok: false, + json: jest.fn().mockResolvedValueOnce(null), + }); + + const service = createMockClaimsService(); + + await expect(service.fetchClaimsConfigurations()).rejects.toThrow( + ClaimsServiceErrorMessages.FAILED_TO_FETCH_CONFIGURATIONS, + ); + }); + }); + describe('getClaims', () => { beforeEach(() => { jest.resetAllMocks(); @@ -98,7 +156,7 @@ describe('ClaimsService', () => { ); expect(mockFetchFunction).toHaveBeenCalledTimes(1); expect(mockFetchFunction).toHaveBeenCalledWith( - `${CLAIMS_API_URL[Env.DEV]}/claims`, + `${CLAIMS_API_URL_MAP[Env.DEV]}/claims`, { headers: { Authorization: 'Bearer test-token', @@ -148,7 +206,7 @@ describe('ClaimsService', () => { ); expect(mockFetchFunction).toHaveBeenCalledTimes(1); expect(mockFetchFunction).toHaveBeenCalledWith( - `${CLAIMS_API_URL[Env.DEV]}/claims/byId/1`, + `${CLAIMS_API_URL_MAP[Env.DEV]}/claims/byId/1`, { headers: { Authorization: 'Bearer test-token', @@ -209,7 +267,7 @@ describe('ClaimsService', () => { ); expect(mockFetchFunction).toHaveBeenCalledTimes(1); expect(mockFetchFunction).toHaveBeenCalledWith( - `${CLAIMS_API_URL[Env.DEV]}/signature/generateMessage`, + `${CLAIMS_API_URL_MAP[Env.DEV]}/signature/generateMessage`, { headers: { Authorization: 'Bearer test-token', diff --git a/packages/claims-controller/src/ClaimsService.ts b/packages/claims-controller/src/ClaimsService.ts index ed6dcf78326..310d7692924 100644 --- a/packages/claims-controller/src/ClaimsService.ts +++ b/packages/claims-controller/src/ClaimsService.ts @@ -3,12 +3,21 @@ import type { AuthenticationController } from '@metamask/profile-sync-controller import type { Hex } from '@metamask/utils'; import { - CLAIMS_API_URL, + CLAIMS_API_URL_MAP, ClaimsServiceErrorMessages, type Env, SERVICE_NAME, } from './constants'; -import type { Claim, GenerateSignatureMessageResponse } from './types'; +import type { + Claim, + ClaimsConfigurationsResponse, + GenerateSignatureMessageResponse, +} from './types'; + +export type ClaimsServiceFetchClaimsConfigurationsAction = { + type: `${typeof SERVICE_NAME}:fetchClaimsConfigurations`; + handler: ClaimsService['fetchClaimsConfigurations']; +}; export type ClaimsServiceGetClaimsAction = { type: `${typeof SERVICE_NAME}:getClaims`; @@ -36,6 +45,7 @@ export type ClaimsServiceGenerateMessageForClaimSignatureAction = { }; export type ClaimsServiceActions = + | ClaimsServiceFetchClaimsConfigurationsAction | ClaimsServiceGetClaimsAction | ClaimsServiceGetClaimByIdAction | ClaimsServiceGetRequestHeadersAction @@ -72,6 +82,10 @@ export class ClaimsService { this.#messenger = messenger; this.#fetch = fetchFunction; + this.#messenger.registerActionHandler( + `${SERVICE_NAME}:fetchClaimsConfigurations`, + this.fetchClaimsConfigurations.bind(this), + ); this.#messenger.registerActionHandler( `${SERVICE_NAME}:getClaims`, this.getClaims.bind(this), @@ -94,6 +108,28 @@ export class ClaimsService { ); } + /** + * Fetch required configurations for the claims service. + * + * @returns The required configurations for the claims service. + */ + async fetchClaimsConfigurations(): Promise { + const headers = await this.getRequestHeaders(); + const url = `${this.getClaimsApiUrl()}/configurations`; + const response = await this.#fetch(url, { + headers, + }); + + if (!response.ok) { + throw new Error( + ClaimsServiceErrorMessages.FAILED_TO_FETCH_CONFIGURATIONS, + ); + } + + const configurations = await response.json(); + return configurations; + } + /** * Get the claims for the current user. * @@ -187,6 +223,6 @@ export class ClaimsService { * @returns The URL for the claims API for the current environment. */ getClaimsApiUrl(): string { - return `${CLAIMS_API_URL[this.#env]}`; + return `${CLAIMS_API_URL_MAP[this.#env]}`; } } diff --git a/packages/claims-controller/src/constants.ts b/packages/claims-controller/src/constants.ts index e5fff384599..a907fc19aad 100644 --- a/packages/claims-controller/src/constants.ts +++ b/packages/claims-controller/src/constants.ts @@ -1,3 +1,5 @@ +import { BuiltInNetworkName, ChainId } from '@metamask/controller-utils'; + export const CONTROLLER_NAME = 'ClaimsController'; export const SERVICE_NAME = 'ClaimsService'; @@ -25,7 +27,7 @@ export enum ClaimStatusEnum { UNKNOWN = 'unknown', } -export const CLAIMS_API_URL: Record = { +export const CLAIMS_API_URL_MAP: Record = { [Env.DEV]: 'https://claims.dev-api.cx.metamask.io', [Env.UAT]: 'https://claims.uat-api.cx.metamask.io', [Env.PRD]: 'https://claims.api.cx.metamask.io', @@ -38,6 +40,7 @@ export const ClaimsControllerErrorMessages = { }; export const ClaimsServiceErrorMessages = { + FAILED_TO_FETCH_CONFIGURATIONS: 'Failed to fetch claims configurations', FAILED_TO_GET_CLAIMS: 'Failed to get claims', FAILED_TO_GET_CLAIM_BY_ID: 'Failed to get claim by id', SIGNATURE_MESSAGE_GENERATION_FAILED: @@ -45,3 +48,14 @@ export const ClaimsServiceErrorMessages = { CLAIM_SIGNATURE_VERIFICATION_REQUEST_FAILED: 'Failed to verify claim signature', }; + +/** + * Default claims configurations. + */ +export const DEFAULT_CLAIMS_CONFIGURATIONS = { + validSubmissionWindowDays: 21, + supportedNetworks: [ + ChainId[BuiltInNetworkName.Mainnet], + ChainId[BuiltInNetworkName.LineaMainnet], + ], +}; diff --git a/packages/claims-controller/src/index.ts b/packages/claims-controller/src/index.ts index 660800ba8bb..e3a74b0f19f 100644 --- a/packages/claims-controller/src/index.ts +++ b/packages/claims-controller/src/index.ts @@ -10,11 +10,17 @@ export type { ClaimsControllerMessenger, } from './ClaimsController'; -export type { Claim, ClaimsControllerState, Attachment } from './types'; +export type { + Claim, + ClaimsControllerState, + Attachment, + ClaimsConfigurations, +} from './types'; export { ClaimsService } from './ClaimsService'; export type { + ClaimsServiceFetchClaimsConfigurationsAction, ClaimsServiceGetClaimsAction, ClaimsServiceGetRequestHeadersAction, ClaimsServiceGetClaimsApiUrlAction, @@ -28,4 +34,7 @@ export { ClaimStatusEnum, Env, ClaimsControllerErrorMessages, + DEFAULT_CLAIMS_CONFIGURATIONS, + ClaimsServiceErrorMessages, + CLAIMS_API_URL_MAP, } from './constants'; diff --git a/packages/claims-controller/src/types.ts b/packages/claims-controller/src/types.ts index 05e9db63557..710ec252234 100644 --- a/packages/claims-controller/src/types.ts +++ b/packages/claims-controller/src/types.ts @@ -8,6 +8,29 @@ export type Attachment = { originalname: string; }; +export type ClaimsConfigurations = { + /** + * The number of days the claim is valid for submission. + */ + validSubmissionWindowDays: number; + + /** + * List of supported chain IDs in hexadecimal format. + */ + supportedNetworks: `0x${string}`[]; +}; + +export type ClaimsConfigurationsResponse = Omit< + ClaimsConfigurations, + 'supportedNetworks' +> & { + /** + * List of supported chain IDs. + * Claims API response for `supportedNetworks` field (in decimal format). + */ + networks: number[]; +}; + export type Claim = { id: string; shortId: string; @@ -30,7 +53,10 @@ export type CreateClaimRequest = Omit< 'id' | 'shortId' | 'createdAt' | 'updatedAt' | 'intercomId' | 'status' >; -export type ClaimsControllerState = { +export type ClaimsControllerState = ClaimsConfigurations & { + /** + * List of claims. + */ claims: Claim[]; }; diff --git a/packages/claims-controller/tests/mocks/messenger.ts b/packages/claims-controller/tests/mocks/messenger.ts index ed50d814df0..3acf3595700 100644 --- a/packages/claims-controller/tests/mocks/messenger.ts +++ b/packages/claims-controller/tests/mocks/messenger.ts @@ -31,6 +31,7 @@ export type RootControllerMessenger = Messenger< * @param params.mockClaimServiceGenerateMessageForClaimSignature - A mock function for the claim service generate message for claim signature. * @param params.mockKeyringControllerSignPersonalMessage - A mock function for the keyring controller sign personal message. * @param params.mockClaimsServiceGetClaims - A mock function for the claim service get claims. + * @param params.mockClaimsServiceFetchClaimsConfigurations - A mock function for the claim service fetch claims configurations. * @returns A mock messenger. */ export function createMockClaimsControllerMessenger({ @@ -39,12 +40,14 @@ export function createMockClaimsControllerMessenger({ mockClaimServiceGenerateMessageForClaimSignature, mockKeyringControllerSignPersonalMessage, mockClaimsServiceGetClaims, + mockClaimsServiceFetchClaimsConfigurations, }: { mockClaimServiceRequestHeaders: jest.Mock; mockClaimServiceGetClaimsApiUrl: jest.Mock; mockClaimServiceGenerateMessageForClaimSignature: jest.Mock; mockKeyringControllerSignPersonalMessage: jest.Mock; mockClaimsServiceGetClaims: jest.Mock; + mockClaimsServiceFetchClaimsConfigurations: jest.Mock; }): { rootMessenger: RootControllerMessenger; messenger: ClaimsControllerMessenger; @@ -57,6 +60,10 @@ export function createMockClaimsControllerMessenger({ namespace: MOCK_ANY_NAMESPACE, }); + rootMessenger.registerActionHandler( + `${SERVICE_NAME}:fetchClaimsConfigurations`, + mockClaimsServiceFetchClaimsConfigurations, + ); rootMessenger.registerActionHandler( `${SERVICE_NAME}:getRequestHeaders`, mockClaimServiceRequestHeaders, @@ -91,6 +98,7 @@ export function createMockClaimsControllerMessenger({ messenger, events: [], actions: [ + `${SERVICE_NAME}:fetchClaimsConfigurations`, `${SERVICE_NAME}:getRequestHeaders`, `${SERVICE_NAME}:getClaimsApiUrl`, `${SERVICE_NAME}:generateMessageForClaimSignature`, From bf3ab7dd04d7ad188d49fb9b80a19ea65505a565 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 11 Nov 2025 14:06:29 +0800 Subject: [PATCH 3/6] chore: updated ChangeLog and tsConfig --- packages/claims-controller/CHANGELOG.md | 7 +++++++ packages/claims-controller/tsconfig.build.json | 3 +++ packages/claims-controller/tsconfig.json | 5 ++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/claims-controller/CHANGELOG.md b/packages/claims-controller/CHANGELOG.md index 4abf3248faf..37b683c69ee 100644 --- a/packages/claims-controller/CHANGELOG.md +++ b/packages/claims-controller/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added new public method, `fetchClaimsConfigurations` to fetch the claims configuration from the Claims backend. ([#7109](https://github.com/MetaMask/core/pull/7109)) +- Added new states fields, `validSubmissionWindowDays` and `supportedNetworks` to the controller state. ([#7109](https://github.com/MetaMask/core/pull/7109)) + - `validSubmissionWindowDays` - number of days the claim is valid for submission. + - `supportedNetworks` - supported networks for the claim submission. + ## [0.1.0] ### Added diff --git a/packages/claims-controller/tsconfig.build.json b/packages/claims-controller/tsconfig.build.json index 63c9b341f96..e144a55d21a 100644 --- a/packages/claims-controller/tsconfig.build.json +++ b/packages/claims-controller/tsconfig.build.json @@ -14,6 +14,9 @@ }, { "path": "../profile-sync-controller/tsconfig.build.json" + }, + { + "path": "../keyring-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] diff --git a/packages/claims-controller/tsconfig.json b/packages/claims-controller/tsconfig.json index 51ec679d169..cf63460ba63 100644 --- a/packages/claims-controller/tsconfig.json +++ b/packages/claims-controller/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.packages.json", "compilerOptions": { - "baseUrl": "./", + "baseUrl": "./" }, "references": [ { @@ -12,6 +12,9 @@ }, { "path": "../profile-sync-controller/tsconfig.json" + }, + { + "path": "../keyring-controller/tsconfig.json" } ], "include": ["../../types", "./src", "./tests"] From 6f00b329ca218d53db276d499694d8d1b8923bc1 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 11 Nov 2025 14:59:16 +0800 Subject: [PATCH 4/6] feat: removed unused types and updated exports --- packages/claims-controller/CHANGELOG.md | 1 + packages/claims-controller/src/index.ts | 2 ++ packages/claims-controller/src/types.ts | 5 ----- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/claims-controller/CHANGELOG.md b/packages/claims-controller/CHANGELOG.md index 37b683c69ee..d8003fe48f2 100644 --- a/packages/claims-controller/CHANGELOG.md +++ b/packages/claims-controller/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new states fields, `validSubmissionWindowDays` and `supportedNetworks` to the controller state. ([#7109](https://github.com/MetaMask/core/pull/7109)) - `validSubmissionWindowDays` - number of days the claim is valid for submission. - `supportedNetworks` - supported networks for the claim submission. +- Exported `CreateClaimRequest` and `SubmitClaimConfig` types from the controller. ([#7109](https://github.com/MetaMask/core/pull/7109)) ## [0.1.0] diff --git a/packages/claims-controller/src/index.ts b/packages/claims-controller/src/index.ts index e3a74b0f19f..420473c9b0c 100644 --- a/packages/claims-controller/src/index.ts +++ b/packages/claims-controller/src/index.ts @@ -15,6 +15,8 @@ export type { ClaimsControllerState, Attachment, ClaimsConfigurations, + CreateClaimRequest, + SubmitClaimConfig, } from './types'; export { ClaimsService } from './ClaimsService'; diff --git a/packages/claims-controller/src/types.ts b/packages/claims-controller/src/types.ts index 710ec252234..99b7027114b 100644 --- a/packages/claims-controller/src/types.ts +++ b/packages/claims-controller/src/types.ts @@ -83,8 +83,3 @@ export type GenerateSignatureMessageResponse = { message: string; nonce: string; }; - -export type VerifyClaimSignatureResponse = { - message: string; - success: boolean; -}; From 7b698bb02369498b8210ffa0f75fa4af96a68cf9 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 11 Nov 2025 15:50:23 +0800 Subject: [PATCH 5/6] fix: added Content-Type header for claim signature message request --- packages/claims-controller/src/ClaimsService.test.ts | 1 + packages/claims-controller/src/ClaimsService.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/claims-controller/src/ClaimsService.test.ts b/packages/claims-controller/src/ClaimsService.test.ts index c6aa8a2c2ed..b730596ed59 100644 --- a/packages/claims-controller/src/ClaimsService.test.ts +++ b/packages/claims-controller/src/ClaimsService.test.ts @@ -271,6 +271,7 @@ describe('ClaimsService', () => { { headers: { Authorization: 'Bearer test-token', + 'Content-Type': 'application/json', }, method: 'POST', body: JSON.stringify({ diff --git a/packages/claims-controller/src/ClaimsService.ts b/packages/claims-controller/src/ClaimsService.ts index 310d7692924..c643a7ee704 100644 --- a/packages/claims-controller/src/ClaimsService.ts +++ b/packages/claims-controller/src/ClaimsService.ts @@ -185,8 +185,11 @@ export class ClaimsService { const headers = await this.getRequestHeaders(); const url = `${this.getClaimsApiUrl()}/signature/generateMessage`; const response = await this.#fetch(url, { - headers, method: 'POST', + headers: { + ...headers, + 'Content-Type': 'application/json', + }, body: JSON.stringify({ chainId, walletAddress, From 9941fe9611b3cad12f32e6ba883ec92c3d69014e Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 11 Nov 2025 17:25:17 +0800 Subject: [PATCH 6/6] feat: updated controller state struct --- packages/claims-controller/CHANGELOG.md | 2 +- .../src/ClaimsController.test.ts | 12 +++++----- .../claims-controller/src/ClaimsController.ts | 23 +++++++------------ packages/claims-controller/src/types.ts | 8 ++++++- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/packages/claims-controller/CHANGELOG.md b/packages/claims-controller/CHANGELOG.md index d8003fe48f2..4d92580a0a4 100644 --- a/packages/claims-controller/CHANGELOG.md +++ b/packages/claims-controller/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added new public method, `fetchClaimsConfigurations` to fetch the claims configuration from the Claims backend. ([#7109](https://github.com/MetaMask/core/pull/7109)) -- Added new states fields, `validSubmissionWindowDays` and `supportedNetworks` to the controller state. ([#7109](https://github.com/MetaMask/core/pull/7109)) +- Added new states fields, `claimsConfigurations` to the controller state. ([#7109](https://github.com/MetaMask/core/pull/7109)) - `validSubmissionWindowDays` - number of days the claim is valid for submission. - `supportedNetworks` - supported networks for the claim submission. - Exported `CreateClaimRequest` and `SubmitClaimConfig` types from the controller. ([#7109](https://github.com/MetaMask/core/pull/7109)) diff --git a/packages/claims-controller/src/ClaimsController.test.ts b/packages/claims-controller/src/ClaimsController.test.ts index 571e7099cf8..b9b3450f6bc 100644 --- a/packages/claims-controller/src/ClaimsController.test.ts +++ b/packages/claims-controller/src/ClaimsController.test.ts @@ -86,12 +86,12 @@ describe('ClaimsController', () => { expect(configurations).toStrictEqual(expectedConfigurations); expect(controller.state).not.toBe(initialState); - expect(controller.state.validSubmissionWindowDays).toBe( - MOCK_CONFIGURATIONS_RESPONSE.validSubmissionWindowDays, - ); - expect(controller.state.supportedNetworks).toStrictEqual( - expectedConfigurations.supportedNetworks, - ); + expect( + controller.state.claimsConfigurations.validSubmissionWindowDays, + ).toBe(MOCK_CONFIGURATIONS_RESPONSE.validSubmissionWindowDays); + expect( + controller.state.claimsConfigurations.supportedNetworks, + ).toStrictEqual(expectedConfigurations.supportedNetworks); }); }); }); diff --git a/packages/claims-controller/src/ClaimsController.ts b/packages/claims-controller/src/ClaimsController.ts index 2655fa500e9..5208237e4ef 100644 --- a/packages/claims-controller/src/ClaimsController.ts +++ b/packages/claims-controller/src/ClaimsController.ts @@ -71,13 +71,7 @@ const ClaimsControllerStateMetadata: StateMetadata = { includeInDebugSnapshot: false, usedInUi: true, }, - validSubmissionWindowDays: { - includeInStateLogs: true, - persist: true, - includeInDebugSnapshot: true, - usedInUi: true, - }, - supportedNetworks: { + claimsConfigurations: { includeInStateLogs: true, persist: true, includeInDebugSnapshot: true, @@ -92,7 +86,7 @@ const ClaimsControllerStateMetadata: StateMetadata = { */ export function getDefaultClaimsControllerState(): ClaimsControllerState { return { - ...DEFAULT_CLAIMS_CONFIGURATIONS, + claimsConfigurations: DEFAULT_CLAIMS_CONFIGURATIONS, claims: [], }; } @@ -124,16 +118,15 @@ export class ClaimsController extends BaseController< const supportedNetworks = configurations.networks.map((network) => toHex(network), ); - - this.update((state) => { - state.validSubmissionWindowDays = - configurations.validSubmissionWindowDays; - state.supportedNetworks = supportedNetworks; - }); - return { + const claimsConfigurations = { validSubmissionWindowDays: configurations.validSubmissionWindowDays, supportedNetworks, }; + + this.update((state) => { + state.claimsConfigurations = claimsConfigurations; + }); + return claimsConfigurations; } /** diff --git a/packages/claims-controller/src/types.ts b/packages/claims-controller/src/types.ts index 99b7027114b..6fc4d59c5b4 100644 --- a/packages/claims-controller/src/types.ts +++ b/packages/claims-controller/src/types.ts @@ -53,11 +53,17 @@ export type CreateClaimRequest = Omit< 'id' | 'shortId' | 'createdAt' | 'updatedAt' | 'intercomId' | 'status' >; -export type ClaimsControllerState = ClaimsConfigurations & { +export type ClaimsControllerState = { /** * List of claims. */ claims: Claim[]; + + /** + * The claims configurations. + * This is used to store the claims configurations fetched from the backend. + */ + claimsConfigurations: ClaimsConfigurations; }; export type SubmitClaimConfig = {