Skip to main content

Create a Snap to estimate gas fees

This tutorial walks you through creating a Snap that estimates gas fees. The Snap uses the fetch API to request information from the internet, and displays custom information in an alert dialog.

Prerequisites

Steps

1. Set up the project

Create a new Snap project using the @metamask/create-snap starter kit by running:

yarn create @metamask/snap gas-estimation-snap

or

npx @metamask/create-snap gas-estimation-snap

or

npm create @metamask/snap gas-estimation-snap

Next, cd into the gas-estimation-snap project directory and run:

yarn install

This initializes your development environment with the required dependencies. You may get a warning similar to the following:

@lavamoat/allow-scripts has detected dependencies without configuration. explicit configuration required.
run "allow-scripts auto" to automatically populate the configuration.

You can resolve this error by running the following command:

yarn run allow-scripts auto

2. Add a custom icon

Your Snap must display an icon in MetaMask. To add a Snap image, create a new folder images in the Snap package packages/snap/:

mkdir packages/snap/images

Download this gas.svg icon file into the ìmages folder you just created.
This is a free icon, "Gas" by Mello from Noun Project.

Your file structure should look like this:

gas-estimation-snap/
├─ packages/
│ ├─ site/
| | |- src/
| | | |- App.tsx
| | ├─ package.json
| | |- ...(react app content)
| |
│ ├─ snap/
| | ├─ images/
| | | |- gas.svg
| | ├─ src/
| | | |- index.test.ts
| | | |- index.ts
| | ├─ snap.manifest.json
| | ├─ package.json
| | |- ... (Snap content)
├─ package.json
├─ ... (other stuff)

Open packages/snap/snap.manifest.json in a text editor. This file contains the main configuration details for your Snap. Edit the npm object, within the location object, and add iconPath with the value "images/gas.svg" to point to your new icon:

snap.manifest.json
"location": {
"npm": {
"filePath": "dist/bundle.js",
"iconPath": "images/gas.svg",
"packageName": "snap",
"registry": "https://registry.npmjs.org/"
}
}

Open packages/snap/package.json in a text editor. Edit the files array and add the images/ folder:

package.json
"files": [
"dist/",
"images/",
"snap.manifest.json"
],

3. Enable network access

To enable your Snap to use the fetch API, enable the endowment:network-access permission by adding "endowment:network-access": {} to the initialPermissions object in snap.manifest.json:

snap.manifest.json
"initialPermissions": {
"snap_dialog": {},
"endowment:rpc": {
"dapps": true,
"snaps": false
},
"endowment:network-access": {}
},
"manifestVersion": "0.1"

4. Fetch gas fee estimates

Open /packages/snap/src/index.ts. This is the main code file for your Snap. To get a gas fee estimate, use the public API endpoint provided by Open Source Ethereum Explorer. Add the following getFees() function to the beginning of the /packages/snap/src/index.ts file:

index.ts
import type { OnRpcRequestHandler } from "@metamask/snaps-sdk";
import { panel, text } from "@metamask/snaps-sdk";

async function getFees() {
const response = await fetch("https://beaconcha.in/api/v1/execution/gasnow");
return response.text();
}

Next, add the copyable component to the second import of the file:

index.ts
import type { OnRpcRequestHandler } from "@metamask/snaps-sdk";
import { panel, text, copyable } from "@metamask/snaps-sdk";

Modify the Snap RPC message handler that displays the dialog. This handler uses a switch statement to handle various request methods, but in this instance there is only one method, hello. For the hello method, the handler returns a call to MetaMask with the parameters to display a dialog, and passes some static strings.

Since getFees() returns a promise, you must use then() to resolve it in your hello method. Update the hello method with the following code:

index.ts
case "hello":
return getFees().then(fees => {
return snap.request({
method: 'snap_dialog',
params: {
type: "alert",
content: panel([
text(`Hello, **${origin}**!`),
text("Current gas fee estimates:"),
copyable(fees),
]),
}
});
});

5. Build and test the Snap

To build and test your Snap:

  1. Open package.json in the root directory of the project, and increment the "version" (if the "version" is 0.1.0, increase it to 0.2.0).

  2. From the command line, run yarn start. In the terminal, at the bottom of the message log, you see the browser URL:

    You can now view site in the browser.

    http://localhost:8000/
  3. Open localhost:8000 in your browser (with MetaMask Flask installed). A page like the following displays:

    Test dapp with template Snap

    This is a boilerplate test dapp for installing and testing your Snap.

  4. Select Connect to connect Flask to the dapp. After connecting, you're prompted to install the Snap with the following permissions:

    • Allow dapps to communicate directly with this Snap.
    • Access the internet.
    • Display dialog windows in MetaMask.
  5. Select Approve > Install.

  6. After installing, the Send message button on the page is enabled. Select this button. A dialog prompt displays with the response from the gas fee API:

Gas estimation dialog

You have integrated a public API into MetaMask and displayed real-time gas fee estimates.

6. Next steps

Next, you can try:

  • Parsing the JSON response from the remote API.
  • Displaying the fees in a nicely formatted way.

You can also update the fields in snap.manifest.json to match your custom Snap:

  • proposedName - The name of your Snap.
  • description - The description of your Snap.
  • source - The shasum is set automatically when you build from the command line. If you decided to publish your Snap to npm, update the location to its published location.

Similarly, you should update the name, version, description, and repository fields of /packages/snap/package.json even if you do not plan to publish your Snap to npm.

important

The version and repository fields in snap.manifest.json inherit the values from package.json and overwrite them in snap.manifest.json. We recommend updating version and repository in package.json first, then building the Snap project.

You can update the content of /packages/site/src/pages/index.tsx by changing the name of the method for showing gas fee estimates. If you change the method name in /packages/site/src/pages/index.tsx, ensure you change the method name in /packages/snap/src/index.ts to match.

After you have made all necessary changes, you can publish your Snap to npm.