diff --git a/packages/examples/packages/ethereum-provider/snap.manifest.json b/packages/examples/packages/ethereum-provider/snap.manifest.json index aab0909c9d..0b546e4f20 100644 --- a/packages/examples/packages/ethereum-provider/snap.manifest.json +++ b/packages/examples/packages/ethereum-provider/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "/yD9JVMe1ppdLCocldK6/6D9Cx0j1+iZQy5Z5INLlEU=", + "shasum": "HQcHCmjI/cTIiFTeAr/PywSGgXUWYUi/otWoHST40h4=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/ethereum-provider/src/index.test.ts b/packages/examples/packages/ethereum-provider/src/index.test.ts index e60536c7ac..1dcca5834b 100644 --- a/packages/examples/packages/ethereum-provider/src/index.test.ts +++ b/packages/examples/packages/ethereum-provider/src/index.test.ts @@ -20,38 +20,53 @@ describe('onRpcRequest', () => { }); }); - describe('getGasPrice', () => { - const MOCK_GAS_PRICE = '0x387c64b64'; - - it('returns the current gas price', async () => { + describe('getGenesisBlock', () => { + // Ethereum Mainnet + const GENESIS_BLOCK = { + difficulty: '0x400000000', + extraData: + '0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa', + gasLimit: '0x1388', + gasUsed: '0x0', + hash: '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', + logsBloom: + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + miner: '0x0000000000000000000000000000000000000000', + mixHash: + '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000042', + number: '0x0', + parentHash: + '0x0000000000000000000000000000000000000000000000000000000000000000', + receiptsRoot: + '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + sha3Uncles: + '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: '0x21c', + stateRoot: + '0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544', + timestamp: '0x0', + transactions: [], + transactionsRoot: + '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + uncles: [], + }; + + it('returns the genesis block', async () => { const { request, mockJsonRpc } = await installSnap(); // To avoid relying on the network, we mock the response from the Ethereum // provider. mockJsonRpc({ - method: 'eth_gasPrice', - result: MOCK_GAS_PRICE, - }); - - const response = await request({ - method: 'getGasPrice', + method: 'eth_getBlockByNumber', + result: GENESIS_BLOCK, }); - expect(response).toRespondWith(MOCK_GAS_PRICE); - }); - }); - - describe('getVersion', () => { - const MOCK_VERSION = '1'; // Ethereum Mainnet - - it('returns the current network version', async () => { - const { request } = await installSnap(); - const response = await request({ - method: 'getVersion', + method: 'getGenesisBlock', }); - expect(response).toRespondWith(MOCK_VERSION); + expect(response).toRespondWith(GENESIS_BLOCK); }); }); diff --git a/packages/examples/packages/ethereum-provider/src/index.ts b/packages/examples/packages/ethereum-provider/src/index.ts index 300a5397ff..c0f0dd8fbb 100644 --- a/packages/examples/packages/ethereum-provider/src/index.ts +++ b/packages/examples/packages/ethereum-provider/src/index.ts @@ -8,6 +8,7 @@ import { stringToBytes, bytesToHex, hexToNumber, + numberToHex, } from '@metamask/utils'; import type { @@ -29,60 +30,47 @@ async function switchChain(chainId: Hex) { } /** - * Get the current gas price using the `ethereum` global. This is essentially + * Get the current chain ID using the `ethereum` global. This is essentially * the same as the `window.ethereum` global, but does not have access to all * methods. * * Note that using the `ethereum` global requires the * `endowment:ethereum-provider` permission. * - * @returns The current gas price as a hexadecimal string. + * @returns The current chain ID as a string. * @see https://docs.metamask.io/snaps/reference/permissions/#endowmentethereum-provider */ -async function getGasPrice() { - const gasPrice = await ethereum.request({ method: 'eth_gasPrice' }); - assert(gasPrice, 'Ethereum provider did not return a gas price.'); - - return gasPrice; -} +async function getChainId() { + const chainId = await ethereum.request({ + method: 'eth_chainId', + }); -/** - * Get the current network version using the `ethereum` global. This is - * essentially the same as the `window.ethereum` global, but does not have - * access to all methods. - * - * Note that using the `ethereum` global requires the - * `endowment:ethereum-provider` permission. - * - * @returns The current network version as a string. - * @see https://docs.metamask.io/snaps/reference/permissions/#endowmentethereum-provider - */ -async function getVersion() { - const version = await ethereum.request({ method: 'net_version' }); - assert(version, 'Ethereum provider did not return a version.'); + assert(chainId, 'Ethereum provider did not return a chain ID.'); - return version; + return chainId; } /** - * Get the current chain ID using the `ethereum` global. This is essentially + * Get a block by number using the `ethereum` global. This is essentially * the same as the `window.ethereum` global, but does not have access to all * methods. * * Note that using the `ethereum` global requires the * `endowment:ethereum-provider` permission. * - * @returns The current chain ID as a string. + * @param blockNumber - The block number. + * @returns Information about the requested block. * @see https://docs.metamask.io/snaps/reference/permissions/#endowmentethereum-provider */ -async function getChainId() { - const chainId = await ethereum.request({ - method: 'eth_chainId', +async function getBlock(blockNumber: number) { + const block = await ethereum.request({ + method: 'eth_getBlockByNumber', + params: [numberToHex(blockNumber), false], }); - assert(chainId, 'Ethereum provider did not return a chain ID.'); + assert(block, 'Ethereum provider did not return a block.'); - return chainId; + return block; } /** @@ -249,18 +237,15 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => { await switchChain(chainId); switch (request.method) { - case 'getGasPrice': - return await getGasPrice(); - - case 'getVersion': - return await getVersion(); - case 'getChainId': return await getChainId(); case 'getAccounts': return await getAccounts(); + case 'getGenesisBlock': + return await getBlock(0); + case 'personalSign': { const params = request.params as PersonalSignParams; const accounts = await getAccounts(); diff --git a/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx b/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx index b6b1d409eb..83b4f0fbe6 100644 --- a/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx +++ b/packages/test-snaps/src/features/snaps/ethereum-provider/EthereumProvider.tsx @@ -29,6 +29,7 @@ export const EthereumProvider: FunctionComponent = () => { }; const handleGetChainId = () => handleSubmit('getChainId'); + const handleGetGenesisBlock = () => handleSubmit('getGenesisBlock'); const handleGetAccounts = () => handleSubmit('getAccounts'); return ( @@ -50,6 +51,15 @@ export const EthereumProvider: FunctionComponent = () => { > Get Chain ID +