Skip to content

Commit

Permalink
Document Snaps tutorials (MetaMask#61)
Browse files Browse the repository at this point in the history
* Document Snaps tutorials

* Document snaps tutorials

* test and finalize gas fee tutorial

* 2nd tutorial

* finalize tutorials

* reviewer feedback
  • Loading branch information
alexandratran authored Mar 28, 2023
1 parent 28447de commit badc87d
Show file tree
Hide file tree
Showing 10 changed files with 416 additions and 23 deletions.
3 changes: 2 additions & 1 deletion snaps-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ const sidebar = {
label: "Tutorials",
link: { type: "generated-index" },
items: [
"tutorials/tutorials",
"tutorials/gas-estimation",
"tutorials/transaction-insights",
],
},
{
Expand Down
Binary file added snaps/assets/gas-estimation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snaps/assets/template-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snaps/assets/transaction-insights.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions snaps/get-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Get started with Snaps using the

- A text editor (for example, [VS Code](https://code.visualstudio.com/))

- [Yarn](https://yarnpkg.com/) version 3

## Create the project

Use the Snaps template by
Expand Down
15 changes: 8 additions & 7 deletions snaps/how-to/develop-a-snap.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Before developing a snap, it's important to understand:
- [The Snaps execution environment](../concepts/execution-environment.md).

You can [get started quickly using the Snaps template](../get-started/quickstart.md) or follow a
[tutorial](../tutorials).
[tutorial](../category/tutorials).

This page describes additional important steps when developing a snap.

Expand Down Expand Up @@ -60,7 +60,7 @@ API methods from a web page.
## Debug your snap
To debug your snap, use `console.log` and inspect the MetaMask background process.
You can add your log statements in your source coder and build your snap, or add them directly
You can add your log statements in your source code and build your snap, or add them directly
to your snap bundle and use `mm-snap manifest --fix` to update the `shasum` in your snap manifest file.
The manifest `shasum` must match the contents of your bundle at the time MetaMask fetches your snap.
Expand All @@ -69,15 +69,16 @@ Because adding logs modifies the snap source code, you must re-install the snap
log statement.
:::
The log output is only visible in the extension background process console.
The snap log output is only visible in the extension background process console.
If you're using a Chromium browser, use the following steps to inspect the background process and
view its console:
1. Go to `chrome://extensions`.
2. Find the MetaMask extension.
3. Select **Details**.
4. Toggle **Developer mode** on in the top right corner.
5. Under **Inspect views**, select `background.html`.
2. Toggle **Developer mode** on in the top right corner.
3. Find MetaMask Flask, and select **Details**.
4. Under **Inspect views**, select `background.html`.

The log output displays in the console that pops up.

## Publish your snap

Expand Down
11 changes: 9 additions & 2 deletions snaps/how-to/manage-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ To derive a user's private keys:
4. Use the [`@metamask/key-tree`](https://github.com/MetaMask/key-tree) module to derive the keys.
Any additional code, for example, to derive addresses from keys, is application-specific.

### Example
### Dogecoin example

For example, to derive Dogecoin keys:

Expand Down Expand Up @@ -101,4 +101,11 @@ For example, to derive Dogecoin keys:

// Derive the second Dogecoin address, which has index 1.
const secondAccount = deriveDogecoinAddress(1);
```
```

## Examples

The following are examples of existing snaps that manage accounts and keys:

- [KeystoneHQ's Btcsnap](https://github.com/KeystoneHQ/btcsnap-1)
- [ConsenSys's Starknet Snap](https://github.com/ConsenSys/starknet-snap)
196 changes: 196 additions & 0 deletions snaps/tutorials/gas-estimation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
description: Create a snap that estimates gas fees.
---

# Create a gas estimation snap

This tutorial walks you through creating a snap that estimates gas fees.
The snap is based on the
[Snaps template](https://github.com/MetaMask/template-snap-monorepo).
It uses the `fetch` API to request information from the internet, and displays custom information in
a confirmation dialog.

## Prerequisites

- [Snaps installed](../get-started/install-snaps.md)

- A text editor (for example, [VS Code](https://code.visualstudio.com/))

- [Yarn](https://yarnpkg.com/) version 3

## Steps

### 1. Set up the project

Use the Snaps template by
[creating a new repository from the template](https://github.com/MetaMask/template-snap-monorepo/generate).

Give your project a new name, such as `gas-estimation-snap`.

[Clone the repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)
using the command line:

```bash
git clone [email protected]:<your-username>/gas-estimation-snap.git
```

To initialize your development environment with the required dependencies, in your project
directory, enter the command `yarn`.

### 2. Set a custom icon

Open `/packages/snap/snap.manifest.json` in a text editor.
This file has the main configuration details for your snap.
Edit the section under `npm` to change the `iconPath` to your new icon:

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

Then, place
[this file](https://raw.githubusercontent.com/Montoya/gas-fee-snap/main/packages/snap/images/gas.svg)
into the `/packages/snap/images` folder.
This is a free icon, **Gas** by Mello from
[Noun Project](https://thenounproject.com/browse/icons/term/gas/).

### 3. Enable network access

To enable your snap to use the `fetch` API, request the
[`endowment:network-access`](../reference/permissions.md#endowment--network-access) permission by
modifying `initialPermissions` in `snap.manifest.json`:

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

### 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](https://beaconcha.in/).
Add the following `getFees()` function to the top of the file:

```typescript title="index.ts"
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();
}
```

Then, 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's
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:

```typescript title="index.ts"
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:

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

2. From the command line, run `yarn start`.
You should get a message that includes:

```bash
You can now view site in the browser.

http://localhost:8000/
```

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

![Test dapp with template snap](../assets/template-snap.png)

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 websites to communicate directly with this snap.**
- **Access the internet.**
- **Display dialog windows in MetaMask.**
5. Select **Approve & install**, then **Send message**.
A dialog prompt displays with the response from the gas fee API:
<p align="center">
![Gas estimation dialog](../assets/gas-estimation.png)
</p>
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 and 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` - 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` sections of
`/packages/snap/package.json` even if you don't plan to publish your snap to npm.
:::note
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.
Once you've made all necessary changes, you can
[publish your snap to npm](../how-to/develop-a-snap.md#publish-your-snap).
Loading

0 comments on commit badc87d

Please sign in to comment.