From f200046fb7598e30070561334eb2994cacad8aa5 Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Thu, 3 Sep 2026 23:11:08 +0800 Subject: [PATCH] Refactor cloud API to introduce getJson function for GET requests and enhance error handling. Updated loadKeyShareBackup to utilize the new function, ensuring consistent response parsing. Added tests to verify the inclusion of the Bearer token in requests. --- packages/keyring-eth-mpc/src/cloud.test.ts | 8 +++ packages/keyring-eth-mpc/src/cloud.ts | 64 +++++++++++++++++----- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/packages/keyring-eth-mpc/src/cloud.test.ts b/packages/keyring-eth-mpc/src/cloud.test.ts index 77f413acd..c0612687f 100644 --- a/packages/keyring-eth-mpc/src/cloud.test.ts +++ b/packages/keyring-eth-mpc/src/cloud.test.ts @@ -304,6 +304,14 @@ describe('cloud helpers', () => { encryptedKeyShare, backupId: 'backup-1', }); + + expect(fetchSpy).toHaveBeenCalledWith( + 'https://cloud.example/load-key-share-backup', + expect.objectContaining({ + method: 'GET', + headers: { Authorization: 'Bearer token-1' }, + }), + ); }); it('throws when loading a key share backup fails', async () => { diff --git a/packages/keyring-eth-mpc/src/cloud.ts b/packages/keyring-eth-mpc/src/cloud.ts index 6fe4d854b..93d6c24de 100644 --- a/packages/keyring-eth-mpc/src/cloud.ts +++ b/packages/keyring-eth-mpc/src/cloud.ts @@ -7,7 +7,51 @@ export type LoadKeyShareBackupResult = { }; /** - * Fetch JSON from the MPC backend, throwing on non-OK responses. + * Parse a fetch response as JSON, throwing on non-OK status. + * + * @param response - The fetch response. + * @param errorPrefix - Prefix for the thrown error message. + * @returns The parsed JSON body, or `undefined` when the response is empty. + */ +async function parseJsonResponse( + response: Response, + errorPrefix: string, +): Promise { + if (!response.ok) { + throw new Error(`${errorPrefix}: ${response.statusText}`); + } + + const text = await response.text(); + if (text.length === 0) { + return undefined as Result; + } + return JSON.parse(text) as Result; +} + +/** + * GET JSON from the MPC backend, throwing on non-OK responses. + * + * @param url - The request URL. + * @param token - Profile token sent as a Bearer header. + * @param errorPrefix - Prefix for the thrown error message. + * @returns The parsed JSON body, or `undefined` when the response is empty. + */ +async function getJson( + url: string, + token: string, + errorPrefix: string, +): Promise { + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + }, + }); + return parseJsonResponse(response, errorPrefix); +} + +/** + * POST JSON to the MPC backend, throwing on non-OK responses. * * @param url - The request URL. * @param token - Profile token sent as a Bearer header. @@ -15,12 +59,12 @@ export type LoadKeyShareBackupResult = { * @param errorPrefix - Prefix for the thrown error message. * @returns The parsed JSON body, or `undefined` when the response is empty. */ -async function postJson( +async function postJson( url: string, token: string, body: Record, errorPrefix: string, -): Promise { +): Promise { const response = await fetch(url, { method: 'POST', headers: { @@ -29,16 +73,7 @@ async function postJson( }, body: JSON.stringify(body), }); - - if (!response.ok) { - throw new Error(`${errorPrefix}: ${response.statusText}`); - } - - const text = await response.text(); - if (text.length === 0) { - return undefined as Response; - } - return JSON.parse(text) as Response; + return parseJsonResponse(response, errorPrefix); } /** @@ -225,13 +260,12 @@ export async function loadKeyShareBackup(opts: { baseURL: string; token: string; }): Promise { - const data = await postJson<{ + const data = await getJson<{ encryptedKeyShare: string; backupId: string; }>( `${opts.baseURL}/load-key-share-backup`, opts.token, - {}, 'Failed to load key share backup', ); return {