From e2662590eb41cb8b601dd3ce044715b142e1a8f4 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 9 Feb 2023 20:40:39 -0330 Subject: [PATCH] Remove `btoa` The `btoa` function must now be passed in as a middleware option. This lets us remove an additional dependency, and makes this package less dependent upon Node.js or browser specific APIs. --- package.json | 1 - src/fetch.test.ts | 19 ++++++++++++++++++- src/fetch.ts | 22 ++++++++++++++++++---- yarn.lock | 10 ---------- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 01f3eeec..5fa92662 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "@metamask/eth-sig-util": "^5.0.0", "@metamask/safe-event-emitter": "^2.0.0", "@metamask/utils": "^3.0.3", - "btoa": "^1.2.1", "clone": "^2.1.1", "eth-block-tracker": "^6.1.0", "eth-rpc-errors": "^4.0.3", diff --git a/src/fetch.test.ts b/src/fetch.test.ts index f7a1bd7e..4a6c4fe6 100644 --- a/src/fetch.test.ts +++ b/src/fetch.test.ts @@ -1,5 +1,17 @@ import { createFetchConfigFromReq } from '.'; +/** + * Generate a base64-encoded string from a binary string. This should be equivalent to + * `window.btoa`. + * + * @param stringToEncode - The string to encode. + * @returns The base64-encoded string. + */ +// eslint-disable-next-line @typescript-eslint/no-shadow +function btoa(stringToEncode: string) { + return Buffer.from(stringToEncode).toString('base64'); +} + describe('fetch', () => { it('should create a fetch config from a request', async () => { const req = { @@ -9,7 +21,11 @@ describe('fetch', () => { params: ['0x482103', true], }; const rpcUrl = 'http://www.xyz.io/rabbit:3456?id=100'; - const { fetchUrl, fetchParams } = createFetchConfigFromReq({ req, rpcUrl }); + const { fetchUrl, fetchParams } = createFetchConfigFromReq({ + btoa, + req, + rpcUrl, + }); expect(fetchUrl).toStrictEqual(rpcUrl); expect(fetchParams).toStrictEqual({ method: 'POST', @@ -32,6 +48,7 @@ describe('fetch', () => { const rpcUrl = 'http://www.xyz.io/rabbit:3456?id=100'; const originHttpHeaderKey = 'x-dapp-origin'; const { fetchUrl, fetchParams } = createFetchConfigFromReq({ + btoa, req: requestWithOrigin, rpcUrl, originHttpHeaderKey, diff --git a/src/fetch.ts b/src/fetch.ts index e2b6aaa9..9d9c3e86 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -6,10 +6,6 @@ import { import { EthereumRpcError, ethErrors } from 'eth-rpc-errors'; import type { Block } from './types'; -/* eslint-disable @typescript-eslint/no-require-imports,@typescript-eslint/no-shadow */ -const btoa = global.btoa || require('btoa'); -/* eslint-enable @typescript-eslint/no-require-imports,@typescript-eslint/no-shadow */ - const RETRIABLE_ERRORS: string[] = [ // ignore server overload errors 'Gateway timeout', @@ -38,6 +34,7 @@ interface FetchConfig { * Create middleware for sending a JSON-RPC request to the given RPC URL. * * @param options - Options + * @param options.btoa - Generates a base64-encoded string from a binary string. * @param options.fetch - The `fetch` function; expected to be equivalent to `window.fetch`. * @param options.rpcUrl - The URL to send the request to. * @param options.originHttpHeaderKey - If provider, the origin field for each JSON-RPC request @@ -45,17 +42,21 @@ interface FetchConfig { * @returns The fetch middleware. */ export function createFetchMiddleware({ + // eslint-disable-next-line @typescript-eslint/no-shadow + btoa, // eslint-disable-next-line @typescript-eslint/no-shadow fetch, rpcUrl, originHttpHeaderKey, }: { + btoa: (stringToEncode: string) => string; fetch: typeof global.fetch; rpcUrl: string; originHttpHeaderKey?: string; }): JsonRpcMiddleware { return createAsyncMiddleware(async (req, res, _next) => { const { fetchUrl, fetchParams } = createFetchConfigFromReq({ + btoa, req, rpcUrl, originHttpHeaderKey, @@ -136,11 +137,24 @@ function parseResponse(fetchRes: Response, body: Record): Block { return body.result; } +/** + * Generate `fetch` configuration for sending the given request to an RPC API. + * + * @param options - Options + * @param options.btoa - Generates a base64-encoded string from a binary string. + * @param options.rpcUrl - The URL to send the request to. + * @param options.originHttpHeaderKey - If provider, the origin field for each JSON-RPC request + * will be attached to each outgoing fetch request under this header. + * @returns The fetch middleware. + */ export function createFetchConfigFromReq({ + // eslint-disable-next-line @typescript-eslint/no-shadow + btoa, req, rpcUrl, originHttpHeaderKey, }: { + btoa: (stringToEncode: string) => string; rpcUrl: string; originHttpHeaderKey?: string; req: PayloadWithOrigin; diff --git a/yarn.lock b/yarn.lock index c8b49666..a2029954 100644 --- a/yarn.lock +++ b/yarn.lock @@ -867,7 +867,6 @@ __metadata: "@types/pify": ^3.0.2 "@typescript-eslint/eslint-plugin": ^4.21.0 "@typescript-eslint/parser": ^4.21.0 - btoa: ^1.2.1 clone: ^2.1.1 eslint: ^7.14.0 eslint-config-prettier: ^8.1.0 @@ -1883,15 +1882,6 @@ __metadata: languageName: node linkType: hard -"btoa@npm:^1.2.1": - version: 1.2.1 - resolution: "btoa@npm:1.2.1" - bin: - btoa: bin/btoa.js - checksum: afbf004fb1b1d530e053ffa66ef5bd3878b101c59d808ac947fcff96810b4452abba2b54be687adadea2ba9efc7af48b04228742789bf824ef93f103767e690c - languageName: node - linkType: hard - "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2"