diff --git a/.eslintrc.js b/.eslintrc.js index e8542989..bd10bb91 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,6 +18,12 @@ module.exports = { sourceType: 'module', }, }, + { + files: ['src/request.js'], + parserOptions: { + sourceType: 'script', + }, + }, ], ignorePatterns: ['!.eslintrc.js', 'dist'], diff --git a/README.md b/README.md index 86824149..bb185b4a 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,12 @@ If you wish to use this dapp in your e2e tests, install this package and set up static-server node_modules/@metamask/test-dapp/dist --port 9011 ``` +The main page of the test dapp includes a simple UI featuring buttons for common dapp interactions. + +There is a second page (`request.html`) that allows making requests directly to the provider using query parameters. This provides a simple way of testing RPC methods using an in-page provider. + +It can be used by navigating to `/request.html?method=${METHOD}¶ms=${PARAMS}` (e.g. `/request.html?method=eth_getLogs¶ms=[{ "address": "0x0000000000000000000000000000000000000000" }]`). The page will make a request with the given RPC method and parameters using `ethereum.request`, and report the result as plain text. + ## Contributing ### Setup diff --git a/src/index.html b/src/index.html index 92105ad8..5484fd4b 100644 --- a/src/index.html +++ b/src/index.html @@ -1029,6 +1029,6 @@

- + diff --git a/src/request.html b/src/request.html new file mode 100644 index 00000000..b265627b --- /dev/null +++ b/src/request.html @@ -0,0 +1,15 @@ + + + + E2E Test Dapp - Send Individual Request + + + + +
+ Initializing +
+ + + + diff --git a/src/request.js b/src/request.js new file mode 100644 index 00000000..b18c29da --- /dev/null +++ b/src/request.js @@ -0,0 +1,97 @@ +/** + * Get the `main` section of the page, ensuring that it is the only + * one present. + */ +function getMainElement() { + const mainElements = document.getElementsByTagName('main'); + + if (mainElements.length === 0) { + throw new Error('Main element not found'); + } else if (mainElements.length > 1) { + throw new Error('Multiple main elements found'); + } + return mainElements[0]; +} + +/** + * Get request data from the query string. + * + * @returns {object} The request data. + */ +function getRequestData() { + const queryString = window.location.search; + + if (queryString.length === 0) { + throw new Error('Request invalid: query string empty'); + } + + const searchParams = new URLSearchParams(queryString); + const method = searchParams.get('method'); + + if (method === null) { + throw new Error('Request invalid: method not provided in query string'); + } + + const rawParams = searchParams.get('params'); + + let params; + if (rawParams !== null) { + try { + params = JSON.parse(rawParams); + } catch (error) { + throw new Error('Request invalid: failed to parse params', { + cause: error, + }); + } + + if (params === null) { + throw new Error(`Request invalid: params parsed as null`); + } else if (typeof params !== 'object') { + throw new Error( + `Request invalid: params parsed as type '${typeof params}'`, + ); + } + } + + const request = { method }; + if (params) { + request.params = params; + } + return request; +} + +/** + * Run the request encoded in the query parameters. + */ +async function main() { + const mainElement = getMainElement(); + + /** + * Log a message, and set it on the page. + * + * @param {string} message - The message to log and set on the page. + */ + function logAndSet(message) { + console.log(message); + mainElement.innerText = message; + } + + try { + if (!window.ethereum) { + throw new Error('Provider not found'); + } + + const requestData = getRequestData(); + + logAndSet(`Sending request: ${JSON.stringify(requestData)}`); + + const result = await window.ethereum.request(requestData); + + logAndSet(`Response: ${JSON.stringify(result)}`); + } catch (error) { + mainElement.innerText = error.message || 'Unknown error'; + throw error; + } +} + +main().catch(console.error); diff --git a/webpack.config.js b/webpack.config.js index 482aaa77..388c70d7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,9 +7,11 @@ const DIST = path.resolve(__dirname, 'dist'); module.exports = { devtool: 'eval-source-map', mode: 'development', - entry: './src/index.js', + entry: { + main: './src/index.js', + request: './src/request.js', + }, output: { - filename: 'bundle.js', path: DIST, publicPath: DIST, },