Skip to content

Commit

Permalink
Use messenger actions instead of KeyringController as constructor p…
Browse files Browse the repository at this point in the history
…aram (#1593)
  • Loading branch information
mikesposito authored and MajorLift committed Oct 11, 2023
1 parent f8ac094 commit 4f54aa6
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 50 deletions.
1 change: 1 addition & 0 deletions packages/signature-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
},
"devDependencies": {
"@metamask/auto-changelog": "^3.1.0",
"@metamask/keyring-controller": "^7.4.0",
"@types/jest": "^27.4.1",
"deepmerge": "^4.2.2",
"jest": "^27.5.1",
Expand Down
80 changes: 55 additions & 25 deletions packages/signature-controller/src/SignatureController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,6 @@ const createMessageManagerMock = <T>(prototype?: any): jest.Mocked<T> => {
}) as jest.Mocked<T>;
};

const createKeyringControllerMock = () => ({
signMessage: jest.fn(),
signPersonalMessage: jest.fn(),
signTypedMessage: jest.fn(),
});

describe('SignatureController', () => {
let signatureController: SignatureController;

Expand All @@ -148,14 +142,28 @@ describe('SignatureController', () => {
error: jest.fn(),
};
const messengerMock = createMessengerMock();
const keyringControllerMock = createKeyringControllerMock();
const getAllStateMock = jest.fn();
const securityProviderRequestMock = jest.fn();
const isEthSignEnabledMock = jest.fn();
const getCurrentChainIdMock = jest.fn();
const keyringErrorMessageMock = 'Keyring Error';
const keyringErrorMock = new Error(keyringErrorMessageMock);

const mockMessengerAction = (
action: string,
callback: (actionName: string, ...args: any[]) => any,
) => {
messengerMock.call.mockImplementation((actionName, ...rest) => {
if (actionName === action) {
return callback(actionName, ...rest);
}

return Promise.resolve({
resultCallbacks: resultCallbacksMock,
});
});
};

beforeEach(() => {
jest.resetAllMocks();
jest.spyOn(console, 'info').mockImplementation(() => undefined);
Expand All @@ -176,7 +184,6 @@ describe('SignatureController', () => {

signatureController = new SignatureController({
messenger: messengerMock,
keyringController: keyringControllerMock,
getAllState: getAllStateMock,
securityProviderRequest: securityProviderRequestMock,
isEthSignEnabled: isEthSignEnabledMock,
Expand Down Expand Up @@ -371,8 +378,9 @@ describe('SignatureController', () => {
undefined,
);

expect(messengerMock.call).toHaveBeenCalledTimes(1);
expect(messengerMock.call).toHaveBeenCalledWith(
expect(messengerMock.call).toHaveBeenCalledTimes(2);
expect(messengerMock.call).toHaveBeenNthCalledWith(
1,
'ApprovalController:addRequest',
{
id: messageIdMock,
Expand All @@ -386,9 +394,9 @@ describe('SignatureController', () => {
});

it('throws if cannot get signature', async () => {
(keyringControllerMock as any).signMessage.mockRejectedValueOnce(
keyringErrorMock,
);
mockMessengerAction('KeyringController:signMessage', async () => {
throw keyringErrorMock;
});
const listenerMock = jest.fn();
signatureController.hub.on(`${messageIdMock}:signError`, listenerMock);

Expand All @@ -404,6 +412,7 @@ describe('SignatureController', () => {
expect(listenerMock).toHaveBeenCalledWith({
error,
});
expect(messengerMock.call).toHaveBeenCalledTimes(2);
expect(error.message).toBe(keyringErrorMessageMock);
expect(messageManagerMock.rejectMessage).toHaveBeenCalledTimes(1);
expect(messageManagerMock.rejectMessage).toHaveBeenCalledWith(
Expand Down Expand Up @@ -443,7 +452,7 @@ describe('SignatureController', () => {
undefined,
);

expect(messengerMock.call).toHaveBeenCalledTimes(1);
expect(messengerMock.call).toHaveBeenCalledTimes(2);
expect(messengerMock.call).toHaveBeenCalledWith(
'ApprovalController:addRequest',
{
Expand All @@ -455,6 +464,11 @@ describe('SignatureController', () => {
},
true,
);
expect(messengerMock.call).toHaveBeenNthCalledWith(
2,
'KeyringController:signPersonalMessage',
messageParamsWithoutIdMock,
);
});

it('throws if approval rejected', async () => {
Expand All @@ -471,17 +485,25 @@ describe('SignatureController', () => {
});

it('throws if cannot get signature', async () => {
(keyringControllerMock as any).signPersonalMessage.mockRejectedValueOnce(
keyringErrorMock,
);
mockMessengerAction('KeyringController:signPersonalMessage', async () => {
throw keyringErrorMock;
});

const error: any = await getError(
async () =>
await signatureController.newUnsignedPersonalMessage(
messageParamsMock,
requestMock,
),
);

expect(messengerMock.call).toHaveBeenCalledTimes(2);
expect(error.message).toBe(keyringErrorMessageMock);
expect(messengerMock.call).toHaveBeenNthCalledWith(
2,
'KeyringController:signPersonalMessage',
messageParamsWithoutIdMock,
);
expect(personalMessageManagerMock.rejectMessage).toHaveBeenCalledTimes(1);
expect(personalMessageManagerMock.rejectMessage).toHaveBeenCalledWith(
messageIdMock,
Expand Down Expand Up @@ -522,8 +544,9 @@ describe('SignatureController', () => {
versionMock,
);

expect(messengerMock.call).toHaveBeenCalledTimes(1);
expect(messengerMock.call).toHaveBeenCalledWith(
expect(messengerMock.call).toHaveBeenCalledTimes(2);
expect(messengerMock.call).toHaveBeenNthCalledWith(
1,
'ApprovalController:addRequest',
{
id: messageIdMock,
Expand All @@ -534,6 +557,12 @@ describe('SignatureController', () => {
},
true,
);
expect(messengerMock.call).toHaveBeenNthCalledWith(
2,
'KeyringController:signTypedMessage',
messageParamsWithoutIdMock,
versionMock,
);
});

it('does not set as signed, messages with deferSetAsSigned', async () => {
Expand Down Expand Up @@ -575,10 +604,11 @@ describe('SignatureController', () => {
{ parseJsonData: true },
);

expect(keyringControllerMock.signTypedMessage).toHaveBeenCalledTimes(1);
expect(keyringControllerMock.signTypedMessage).toHaveBeenCalledWith(
expect(messengerMock.call).toHaveBeenNthCalledWith(
2,
'KeyringController:signTypedMessage',
{ ...messageParamsMock2, data: jsonData, deferSetAsSigned: false },
{ version: 'V2' },
'V2',
);
});

Expand All @@ -598,9 +628,9 @@ describe('SignatureController', () => {
});

it('throws if cannot get signature', async () => {
keyringControllerMock.signTypedMessage.mockRejectedValueOnce(
keyringErrorMock,
);
mockMessengerAction('KeyringController:signTypedMessage', async () => {
throw keyringErrorMock;
});
typedMessageManagerMock.addUnapprovedMessage.mockResolvedValue(
messageIdMock,
);
Expand Down
46 changes: 22 additions & 24 deletions packages/signature-controller/src/SignatureController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import type {
import type { RestrictedControllerMessenger } from '@metamask/base-controller';
import { BaseControllerV2 } from '@metamask/base-controller';
import { ApprovalType, ORIGIN_METAMASK } from '@metamask/controller-utils';
import type {
KeyringControllerSignMessageAction,
KeyringControllerSignPersonalMessageAction,
KeyringControllerSignTypedMessageAction,
SignTypedDataVersion,
} from '@metamask/keyring-controller';
import type {
MessageParams,
MessageParamsMetamask,
Expand Down Expand Up @@ -72,7 +78,11 @@ type SignatureControllerState = {
unapprovedTypedMessagesCount: number;
};

type AllowedActions = AddApprovalRequest;
type AllowedActions =
| AddApprovalRequest
| KeyringControllerSignMessageAction
| KeyringControllerSignPersonalMessageAction
| KeyringControllerSignTypedMessageAction;

type TypedMessageSigningOptions = {
parseJsonData: boolean;
Expand Down Expand Up @@ -100,20 +110,8 @@ export type SignatureControllerMessenger = RestrictedControllerMessenger<
never
>;

export interface KeyringController {
signMessage: (messsageParams: MessageParams) => Promise<string>;
signPersonalMessage: (
messsageParams: PersonalMessageParams,
) => Promise<string>;
signTypedMessage: (
messsageParams: TypedMessageParams,
options: { version: string | undefined },
) => Promise<string>;
}

export type SignatureControllerOptions = {
messenger: SignatureControllerMessenger;
keyringController: KeyringController;
isEthSignEnabled: () => boolean;
getAllState: () => unknown;
securityProviderRequest?: (
Expand All @@ -133,8 +131,6 @@ export class SignatureController extends BaseControllerV2<
> {
hub: EventEmitter;

#keyringController: KeyringController;

#isEthSignEnabled: () => boolean;

#getAllState: () => any;
Expand All @@ -150,15 +146,13 @@ export class SignatureController extends BaseControllerV2<
*
* @param options - The controller options.
* @param options.messenger - The restricted controller messenger for the sign controller.
* @param options.keyringController - An instance of a keyring controller used to perform the signing operations.
* @param options.isEthSignEnabled - Callback to return true if eth_sign is enabled.
* @param options.getAllState - Callback to retrieve all user state.
* @param options.securityProviderRequest - A function for verifying a message, whether it is malicious or not.
* @param options.getCurrentChainId - A function for retrieving the current chainId.
*/
constructor({
messenger,
keyringController,
isEthSignEnabled,
getAllState,
securityProviderRequest,
Expand All @@ -171,7 +165,6 @@ export class SignatureController extends BaseControllerV2<
state: getDefaultState(),
});

this.#keyringController = keyringController;
this.#isEthSignEnabled = isEthSignEnabled;
this.#getAllState = getAllState;

Expand Down Expand Up @@ -525,7 +518,10 @@ export class SignatureController extends BaseControllerV2<
ApprovalType.EthSign,
msgParams,
async (cleanMsgParams) =>
await this.#keyringController.signMessage(cleanMsgParams),
await this.messagingSystem.call(
'KeyringController:signMessage',
cleanMsgParams,
),
);
}

Expand All @@ -542,7 +538,10 @@ export class SignatureController extends BaseControllerV2<
ApprovalType.PersonalSign,
msgParams,
async (cleanMsgParams) =>
await this.#keyringController.signPersonalMessage(cleanMsgParams),
await this.messagingSystem.call(
'KeyringController:signPersonalMessage',
cleanMsgParams,
),
);
}

Expand Down Expand Up @@ -570,11 +569,10 @@ export class SignatureController extends BaseControllerV2<
? this.#removeJsonData(cleanMsgParams, version as string)
: cleanMsgParams;

return await this.#keyringController.signTypedMessage(
return await this.messagingSystem.call(
'KeyringController:signTypedMessage',
finalMessageParams,
{
version,
},
version as SignTypedDataVersion,
);
},
);
Expand Down
3 changes: 3 additions & 0 deletions packages/signature-controller/tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
},
{
"path": "../message-manager/tsconfig.build.json"
},
{
"path": "../keyring-controller/tsconfig.build.json"
}
],
"include": ["../../types", "./src"]
Expand Down
3 changes: 3 additions & 0 deletions packages/signature-controller/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
},
{
"path": "../message-manager"
},
{
"path": "../keyring-controller"
}
],
"include": ["../../types", "./src"]
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1790,7 +1790,7 @@ __metadata:
languageName: unknown
linkType: soft

"@metamask/keyring-controller@workspace:packages/keyring-controller":
"@metamask/keyring-controller@^7.4.0, @metamask/keyring-controller@workspace:packages/keyring-controller":
version: 0.0.0-use.local
resolution: "@metamask/keyring-controller@workspace:packages/keyring-controller"
dependencies:
Expand Down Expand Up @@ -2114,6 +2114,7 @@ __metadata:
"@metamask/auto-changelog": ^3.1.0
"@metamask/base-controller": ^3.2.1
"@metamask/controller-utils": ^4.3.2
"@metamask/keyring-controller": ^7.4.0
"@metamask/message-manager": ^7.3.1
"@metamask/utils": ^6.2.0
"@types/jest": ^27.4.1
Expand Down

0 comments on commit 4f54aa6

Please sign in to comment.