Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

Commit

Permalink
refactor: make exportAccount, listRequests and getRequest optio…
Browse files Browse the repository at this point in the history
…nal (#73)
  • Loading branch information
danroc authored Aug 24, 2023
1 parent 16da4ef commit f54a39c
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 32 deletions.
6 changes: 3 additions & 3 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export type Keyring = {
* @param id - The ID of the account to export.
* @returns A promise that resolves to the exported account.
*/
exportAccount(id: string): Promise<KeyringAccountData>;
exportAccount?(id: string): Promise<KeyringAccountData>;

/**
* List all submitted requests.
Expand All @@ -221,7 +221,7 @@ export type Keyring = {
*
* @returns A promise that resolves to an array of KeyringRequest objects.
*/
listRequests(): Promise<KeyringRequest[]>;
listRequests?(): Promise<KeyringRequest[]>;

/**
* Get a request.
Expand All @@ -232,7 +232,7 @@ export type Keyring = {
* @returns A promise that resolves to the KeyringRequest object if found, or
* undefined otherwise.
*/
getRequest(id: string): Promise<KeyringRequest | undefined>;
getRequest?(id: string): Promise<KeyringRequest | undefined>;

/**
* Submit a request.
Expand Down
73 changes: 73 additions & 0 deletions src/rpc-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,44 @@ describe('keyringRpcDispatcher', () => {
expect(result).toBe('DeleteAccount result');
});

it('should call keyring_exportAccount', async () => {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
id: '7c507ff0-365f-4de0-8cd5-eb83c30ebda4',
method: 'keyring_exportAccount',
params: { id: '4f983fa2-4f53-4c63-a7c2-f9a5ed750041' },
};
const expected = {
privateKey: '0x0123',
};

keyring.exportAccount.mockResolvedValue(expected);
const result = await handleKeyringRequest(keyring, request);

expect(keyring.exportAccount).toHaveBeenCalledWith(
'4f983fa2-4f53-4c63-a7c2-f9a5ed750041',
);
expect(result).toStrictEqual(expected);
});

it('should throw MethodNotSupportedError if exportAccount is not implemented', async () => {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
id: '7c507ff0-365f-4de0-8cd5-eb83c30ebda4',
method: 'keyring_exportAccount',
params: { id: '4f983fa2-4f53-4c63-a7c2-f9a5ed750041' },
};

const partialKeyring: Keyring = {
...keyring,
};
delete partialKeyring.exportAccount;

await expect(handleKeyringRequest(partialKeyring, request)).rejects.toThrow(
MethodNotSupportedError,
);
});

it('should call keyring_listRequests', async () => {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
Expand All @@ -289,6 +327,23 @@ describe('keyringRpcDispatcher', () => {
expect(result).toBe('ListRequests result');
});

it('should throw MethodNotSupportedError if listRequests is not implemented', async () => {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
id: '7c507ff0-365f-4de0-8cd5-eb83c30ebda4',
method: 'keyring_listRequests',
};

const partialKeyring: Keyring = {
...keyring,
};
delete partialKeyring.listRequests;

await expect(handleKeyringRequest(partialKeyring, request)).rejects.toThrow(
MethodNotSupportedError,
);
});

it('should call keyring_getRequest', async () => {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
Expand All @@ -304,6 +359,24 @@ describe('keyringRpcDispatcher', () => {
expect(result).toBe('GetRequest result');
});

it('should throw MethodNotSupportedError if getRequest is not implemented', async () => {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
id: '7c507ff0-365f-4de0-8cd5-eb83c30ebda4',
method: 'keyring_getRequest',
params: { id: 'request_id' },
};

const partialKeyring: Keyring = {
...keyring,
};
delete partialKeyring.getRequest;

await expect(handleKeyringRequest(partialKeyring, request)).rejects.toThrow(
MethodNotSupportedError,
);
});

it('should call keyring_submitRequest', async () => {
const dappRequest = {
account: '4abdd17e-8b0f-4d06-a017-947a64823b3d',
Expand Down
81 changes: 52 additions & 29 deletions src/rpc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
CreateAccountRequestStruct,
ApproveRequestRequestStruct,
DeleteAccountRequestStruct,
ExportAccountRequestStruct,
GetRequestRequestStruct,
RejectRequestRequestStruct,
SubmitRequestRequestStruct,
Expand Down Expand Up @@ -58,6 +59,21 @@ export function buildHandlersChain(
};
}

export enum KeyringRpcMethod {
ListAccounts = 'keyring_listAccounts',
GetAccount = 'keyring_getAccount',
CreateAccount = 'keyring_createAccount',
FilterAccountChains = 'keyring_filterAccountChains',
UpdateAccount = 'keyring_updateAccount',
DeleteAccount = 'keyring_deleteAccount',
ExportAccount = 'keyring_exportAccount',
ListRequests = 'keyring_listRequests',
GetRequest = 'keyring_getRequest',
SubmitRequest = 'keyring_submitRequest',
ApproveRequest = 'keyring_approveRequest',
RejectRequest = 'keyring_rejectRequest',
}

/**
* Handles a keyring JSON-RPC request.
*
Expand All @@ -74,75 +90,82 @@ export async function handleKeyringRequest(
assert(request, JsonRpcRequestStruct);

switch (request.method) {
case 'keyring_listAccounts': {
case KeyringRpcMethod.ListAccounts: {
assert(request, ListAccountsRequestStruct);
return await keyring.listAccounts();
return keyring.listAccounts();
}

case 'keyring_getAccount': {
case KeyringRpcMethod.GetAccount: {
assert(request, GetAccountRequestStruct);
return await keyring.getAccount(request.params.id);
return keyring.getAccount(request.params.id);
}

case 'keyring_createAccount': {
case KeyringRpcMethod.CreateAccount: {
assert(request, CreateAccountRequestStruct);
return await keyring.createAccount(request.params.options);
return keyring.createAccount(request.params.options);
}

case 'keyring_filterAccountChains': {
case KeyringRpcMethod.FilterAccountChains: {
assert(request, FilterAccountChainsStruct);
return await keyring.filterAccountChains(
return keyring.filterAccountChains(
request.params.id,
request.params.chains,
);
}

case 'keyring_updateAccount': {
case KeyringRpcMethod.UpdateAccount: {
assert(request, UpdateAccountRequestStruct);
return await keyring.updateAccount(request.params.account);
return keyring.updateAccount(request.params.account);
}

case 'keyring_deleteAccount': {
case KeyringRpcMethod.DeleteAccount: {
assert(request, DeleteAccountRequestStruct);
return await keyring.deleteAccount(request.params.id);
return keyring.deleteAccount(request.params.id);
}

case 'keyring_listRequests': {
case KeyringRpcMethod.ExportAccount: {
if (keyring.exportAccount === undefined) {
throw new MethodNotSupportedError(request.method);
}
assert(request, ExportAccountRequestStruct);
return keyring.exportAccount(request.params.id);
}

case KeyringRpcMethod.ListRequests: {
if (keyring.listRequests === undefined) {
throw new MethodNotSupportedError(request.method);
}
assert(request, ListRequestsRequestStruct);
return await keyring.listRequests();
return keyring.listRequests();
}

case 'keyring_getRequest': {
case KeyringRpcMethod.GetRequest: {
if (keyring.getRequest === undefined) {
throw new MethodNotSupportedError(request.method);
}
assert(request, GetRequestRequestStruct);
return await keyring.getRequest(request.params.id);
return keyring.getRequest(request.params.id);
}

case 'keyring_submitRequest': {
case KeyringRpcMethod.SubmitRequest: {
assert(request, SubmitRequestRequestStruct);
return await keyring.submitRequest(request.params);
return keyring.submitRequest(request.params);
}

case 'keyring_approveRequest': {
// This is an optional method, so we have to check if it exists.
case KeyringRpcMethod.ApproveRequest: {
if (keyring.approveRequest === undefined) {
throw new MethodNotSupportedError(request.method);
}

assert(request, ApproveRequestRequestStruct);
return await keyring.approveRequest(
request.params.id,
request.params.data,
);
return keyring.approveRequest(request.params.id, request.params.data);
}

case 'keyring_rejectRequest': {
// This is an optional method, so we have to check if it exists.
case KeyringRpcMethod.RejectRequest: {
if (keyring.rejectRequest === undefined) {
throw new MethodNotSupportedError(request.method);
}

assert(request, RejectRequestRequestStruct);
return await keyring.rejectRequest(request.params.id);
return keyring.rejectRequest(request.params.id);
}

default: {
Expand Down

0 comments on commit f54a39c

Please sign in to comment.