Create a gas estimation snap
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 a confirmation dialog.
Prerequisites
- Snaps installed
- A text editor (for example, VS Code)
- Yarn version 3
Steps
1. Set up the project
Create a new snap project using the @metamask/create-snap
CLI by running:
yarn create @metamask/snap gas-estimation-snap
or
npm create @metamask/snap gas-estimation-snap
Next, cd
into the gas-estimation-map
project directory and run:
yarn install
This initializes your development environment with the required dependencies.
2. Set a custom icon
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 change the value for the iconPath
key by giving the path "images/gas.svg"
to your new icon:
"location": {
"npm": {
"filePath": "dist/bundle.js",
"iconPath": "images/gas.svg",
"packageName": "snap",
"registry": "https://registry.npmjs.org/"
}
}
Next, download this gas.svg
icon file into the /packages/snap/images
folder.
This is a free icon, Gas by Mello from
Noun Project.
3. Enable network access
To enable your snap to use the fetch
API, make a request for the
endowment:network-access
permission by
adding "endowment:network-access": {}
to the initialPermissions
object in 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 top of the file:
import { OnRpcRequestHandler } from '@metamask/snaps-types';
import { panel, text } from '@metamask/snaps-ui';
async function getFees() {
const response = await fetch('https://beaconcha.in/api/v1/execution/gasnow');
return response.text();
}
Next, modify the snap RPC message handler that displays the confirmation window.
This handler uses a switch statement to handle various request methods, but in this case there is
only one method, hello
.
For this method, the handler returns a call to MetaMask with the parameters to display a
confirmation window, and passes some static strings.
Since getFees()
returns a promise, you must use then()
to resolve it in your hello
method.
Rewrite the hello
method with the following code:
export const onRpcRequest: OnRpcRequestHandler = ({ origin, request }) => {
switch (request.method) {
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: ${fees}`),
]),
}
});
});
default:
throw new Error('Method not found.');
}
};
5. Build and test the snap
To build and test your snap:
Open
package.json
in the root directory of the project, and increase the"version"
(if the"version"
is0.1.0
, increase it to0.2.0
).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/Open
localhost:8000
in your browser (with MetaMask Flask installed). A page like the following displays:This is a boilerplate test dapp for installing and testing your snap.
Select Connect to connect Flask to the dapp. After connecting, you're prompted to install the snap with the following permissions:
- Allow websites to communicate directly with this snap.
- Access the internet.
- Display dialog windows in MetaMask.
Select Approve & install.
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:
Congratulations! You've 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.repository
- The URL of your cloned GitHub repository.source
- Theshasum
is set automatically when you build from the command line. If you decided to publish your snap to npm, update thelocation
to its published location.
Similarly, you should update the name
, version
, description
, and repository
sections of
/packages/snap/package.json
even if you do not plan to publish your snap to npm
.
The version
field in snap.manifest.json
inherits the version
field from package.json
.
Lastly, you can update the content of /packages/site/src/pages/index.tsx
, such as changing the
name of the method for showing gas fee estimates.
If you change the method name, make sure to 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.