diff --git a/packages/signature-controller/src/SignatureController.test.ts b/packages/signature-controller/src/SignatureController.test.ts index cbe2eb5772..368772bec2 100644 --- a/packages/signature-controller/src/SignatureController.test.ts +++ b/packages/signature-controller/src/SignatureController.test.ts @@ -927,7 +927,10 @@ describe('SignatureController', () => { }, ], }; - const { controller } = createController(); + const { controller } = createController({ + decodingApiUrl: 'www.test.com', + isDecodeSignatureRequestEnabled: () => true, + }); jest .spyOn(DecodingDataUtils, 'decodeSignature') @@ -948,8 +951,74 @@ describe('SignatureController', () => { ).toStrictEqual(MOCK_STATE_CHANGES); }); + it('does not invoke decodeSignature if decodingApiUrl is not defined', async () => { + const { controller } = createController({ + decodingApiUrl: undefined, + isDecodeSignatureRequestEnabled: () => true, + }); + + await controller.newUnsignedTypedMessage( + PERMIT_PARAMS_MOCK, + PERMIT_REQUEST_MOCK, + SignTypedDataVersion.V4, + { parseJsonData: false }, + ); + + expect( + controller.state.signatureRequests[ID_MOCK].decodingLoading, + ).toBeUndefined(); + expect( + controller.state.signatureRequests[ID_MOCK].decodingData, + ).toBeUndefined(); + }); + + it('does not invoke decodeSignature if featureFLag disableDecodingApi is true', async () => { + const { controller } = createController({ + decodingApiUrl: 'www.test.com', + isDecodeSignatureRequestEnabled: () => false, + }); + + await controller.newUnsignedTypedMessage( + PERMIT_PARAMS_MOCK, + PERMIT_REQUEST_MOCK, + SignTypedDataVersion.V4, + { parseJsonData: false }, + ); + + expect( + controller.state.signatureRequests[ID_MOCK].decodingLoading, + ).toBeUndefined(); + expect( + controller.state.signatureRequests[ID_MOCK].decodingData, + ).toBeUndefined(); + }); + + it('does not invoke decodeSignature if isDecodeSignatureRequestEnabled is not defined', async () => { + const { controller } = createController({ + decodingApiUrl: 'www.test.com', + isDecodeSignatureRequestEnabled: undefined, + }); + + await controller.newUnsignedTypedMessage( + PERMIT_PARAMS_MOCK, + PERMIT_REQUEST_MOCK, + SignTypedDataVersion.V4, + { parseJsonData: false }, + ); + + expect( + controller.state.signatureRequests[ID_MOCK].decodingLoading, + ).toBeUndefined(); + expect( + controller.state.signatureRequests[ID_MOCK].decodingData, + ).toBeUndefined(); + }); + it('correctly set decoding data if decodeSignature fails', async () => { - const { controller } = createController(); + const { controller } = createController({ + decodingApiUrl: 'www.test.com', + isDecodeSignatureRequestEnabled: () => true, + }); jest .spyOn(DecodingDataUtils, 'decodeSignature') @@ -973,7 +1042,10 @@ describe('SignatureController', () => { }); it('set decodingLoading to true while api request is in progress', async () => { - const { controller } = createController(); + const { controller } = createController({ + decodingApiUrl: 'www.test.com', + isDecodeSignatureRequestEnabled: () => true, + }); jest .spyOn(DecodingDataUtils, 'decodeSignature') diff --git a/packages/signature-controller/src/SignatureController.ts b/packages/signature-controller/src/SignatureController.ts index 21ed60bc89..86660b0cb1 100644 --- a/packages/signature-controller/src/SignatureController.ts +++ b/packages/signature-controller/src/SignatureController.ts @@ -161,6 +161,11 @@ export type SignatureControllerOptions = { */ decodingApiUrl?: string; + /** + * Function to check if decoding signature request is enabled + */ + isDecodeSignatureRequestEnabled?: () => boolean; + /** * Initial state of the controller. */ @@ -184,19 +189,23 @@ export class SignatureController extends BaseController< #decodingApiUrl?: string; + #isDecodeSignatureRequestEnabled?: () => boolean; + #trace: TraceCallback; /** * Construct a Sign controller. * * @param options - The controller options. + * @param options.decodingApiUrl - Api used to get decoded data for permits. + * @param options.isDecodeSignatureRequestEnabled - Function to check is decoding signature request is enabled. * @param options.messenger - The restricted controller messenger for the sign controller. * @param options.state - Initial state to set on this controller. * @param options.trace - Callback to generate trace information. - * @param options.decodingApiUrl - Api used to get decoded data for permits. */ constructor({ decodingApiUrl, + isDecodeSignatureRequestEnabled, messenger, state, trace, @@ -214,6 +223,7 @@ export class SignatureController extends BaseController< this.hub = new EventEmitter(); this.#trace = trace ?? (((_request, fn) => fn?.()) as TraceCallback); this.#decodingApiUrl = decodingApiUrl; + this.#isDecodeSignatureRequestEnabled = isDecodeSignatureRequestEnabled; } /** @@ -902,6 +912,9 @@ export class SignatureController extends BaseController< request: OriginalRequest, chainId: string, ) { + if (!this.#isDecodeSignatureRequestEnabled?.() || !this.#decodingApiUrl) { + return; + } this.#updateMetadata(signatureRequestId, (draftMetadata) => { draftMetadata.decodingLoading = true; }); diff --git a/packages/signature-controller/src/constants.ts b/packages/signature-controller/src/constants.ts deleted file mode 100644 index 93cbf22f8c..0000000000 --- a/packages/signature-controller/src/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Supported signature methods. - */ -export const EthMethod = { - PersonalSign: 'personal_sign', - SignTransaction: 'eth_signTransaction', - SignTypedDataV1: 'eth_signTypedData_v1', - SignTypedDataV3: 'eth_signTypedData_v3', - SignTypedDataV4: 'eth_signTypedData_v4', -}; diff --git a/packages/signature-controller/src/types.ts b/packages/signature-controller/src/types.ts index c6e8b7c48c..b4610a96cd 100644 --- a/packages/signature-controller/src/types.ts +++ b/packages/signature-controller/src/types.ts @@ -2,6 +2,27 @@ import type { SIWEMessage } from '@metamask/controller-utils'; import type { SignTypedDataVersion } from '@metamask/keyring-controller'; import type { Hex, Json } from '@metamask/utils'; +/** + * Supported signature methods. + */ +export enum EthMethod { + PersonalSign = 'personal_sign', + SignTransaction = 'eth_signTransaction', + SignTypedDataV1 = 'eth_signTypedData_v1', + SignTypedDataV3 = 'eth_signTypedData_v3', + SignTypedDataV4 = 'eth_signTypedData_v4', +} + +/** Different decoding data state change types */ +export enum DecodingDataChangeType { + Receive = 'RECEIVE', + Transfer = 'TRANSFER', + Approve = 'APPROVE', + Revoke = 'REVOKE_APPROVE', + Bidding = 'BIDDING', + Listing = 'LISTING', +} + /** Original client request that triggered the signature request. */ export type OriginalRequest = { /** Unique ID to identify the client request. */ @@ -81,19 +102,10 @@ export type MessageParamsTyped = MessageParams & { version?: string; }; -/** Different decoding data state change types */ -export type DecodingDataChangeType = - | 'RECEIVE' - | 'TRANSFER' - | 'APPROVE' - | 'REVOKE_APPROVE' - | 'BIDDING' - | 'LISTING'; - /** Information about a single state change returned by decoding api. */ export type DecodingDataStateChange = { assetType: string; - changeType: DecodingDataChangeType; + changeType: (typeof DecodingDataChangeType)[keyof typeof DecodingDataChangeType]; address: string; amount: string; contractAddress: string; diff --git a/packages/signature-controller/src/utils/decoding-api.test.ts b/packages/signature-controller/src/utils/decoding-api.test.ts index 67f66bc0cc..e8ee61d31c 100644 --- a/packages/signature-controller/src/utils/decoding-api.test.ts +++ b/packages/signature-controller/src/utils/decoding-api.test.ts @@ -1,5 +1,4 @@ -import { EthMethod } from '../constants'; -import { type OriginalRequest } from '../types'; +import { EthMethod, type OriginalRequest } from '../types'; import { decodeSignature } from './decoding-api'; const PERMIT_REQUEST_MOCK = { diff --git a/packages/signature-controller/src/utils/decoding-api.ts b/packages/signature-controller/src/utils/decoding-api.ts index b4baddab24..fbbfe4518b 100644 --- a/packages/signature-controller/src/utils/decoding-api.ts +++ b/packages/signature-controller/src/utils/decoding-api.ts @@ -1,5 +1,4 @@ -import { EthMethod } from '../constants'; -import { type OriginalRequest } from '../types'; +import { EthMethod, type OriginalRequest } from '../types'; import { convertNumericValuesToQuotedString } from './normalize'; export const DECODING_API_ERRORS = { @@ -18,11 +17,8 @@ export const DECODING_API_ERRORS = { export async function decodeSignature( request: OriginalRequest, chainId: string, - decodingApiUrl?: string, + decodingApiUrl: string, ) { - if (!decodingApiUrl) { - return undefined; - } try { const { method, origin, params } = request; if (request.method === EthMethod.SignTypedDataV4) {