Skip to content

Commit

Permalink
Document Snaps network access (MetaMask#1301)
Browse files Browse the repository at this point in the history
* Document Snaps network access

* Update network-access.md

Add one line about using a proxy if fetch is blocked by remote server.

* add proxy resource

---------

Co-authored-by: Christian Montoya <[email protected]>
  • Loading branch information
alexandratran and Montoya authored May 8, 2024
1 parent 83c8447 commit feee275
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 22 deletions.
2 changes: 2 additions & 0 deletions docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ of the [MetaMask developer page](https://metamask.io/developer/).

## May 2024

- Documented [Snaps network access](/snaps/features/network-access).
([#1301](https://github.com/MetaMask/metamask-docs/pull/1301))
- Documented [provider API methods for removing event listeners](/wallet/reference/provider-api/#remove-event-listeners).
([#1288](https://github.com/MetaMask/metamask-docs/pull/1288))

Expand Down
59 changes: 59 additions & 0 deletions snaps/features/network-access.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
description: Access the internet using the fetch function.
sidebar_position: 8
---

# Network access

You can access the internet from a Snap using the global `fetch` API.

## Steps

### 1. Request permission to access the internet

Request the [`endowment:network-access`](../reference/permissions.md#endowmentnetwork-access) permission,
which exposes the global `fetch` API to the Snaps execution environment.
Add the following to your Snap's manifest file:

```json title="snap.manifest.json"
"initialPermissions": {
"endowment:network-access": {}
}
```

### 2. Use the `fetch` function

You can now use the `fetch` function to access the internet.
The following example fetches a JSON file from the provided URL.

```ts title="index.ts"
async function getJson(url: string) {
const response = await fetch(url);
return await response.json();
}
```

:::info Same-origin policy and CORS
`fetch` requests in a Snap are bound by the browser's
[same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#cross-origin_network_access).
Since Snap code is executed in an iframe with the `sandbox` property, the browser sends an `Origin`
header with the value `null` with outgoing requests.
For the Snap to be able to read the response, the server must send an
[`Access-Control-Allow-Origin`](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) CORS header
with the value `*` or `null` in the response.
Otherwise, you might need to
[set up a proxy](https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141#43881141).
:::

:::caution
`XMLHttpRequest` isn't available in Snaps, and you should replace it with `fetch`.
If your dependencies use `XMLHttpRequest`, you can
[patch it away](../how-to/debug-a-snap/common-issues.md#patch-the-use-of-xmlhttprequest).
:::

## Example

See the [`@metamask/network-access-example-snap`](https://github.com/MetaMask/snaps/tree/main/packages/examples/packages/network-access)
package for a full example of accessing the internet from a Snap.
This example exposes a [custom JSON-RPC API](../learn/about-snaps/apis.md#custom-json-rpc-apis) for
dapps to call the `fetch` function from a Snap.
2 changes: 1 addition & 1 deletion snaps/features/non-evm-networks.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Manage users' non-EVM accounts and assets.
sidebar_position: 8
sidebar_position: 9
---

# Non-EVM networks
Expand Down
2 changes: 1 addition & 1 deletion snaps/features/notifications.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Notify users directly in MetaMask, or natively in their OS.
sidebar_position: 9
sidebar_position: 10
---

# Notifications
Expand Down
2 changes: 1 addition & 1 deletion snaps/features/signature-insights.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Provide insights to your users in MetaMask's signature confirmation flow.
sidebar_position: 10
sidebar_position: 11
sidebar_custom_props:
flask_only: true
---
Expand Down
2 changes: 1 addition & 1 deletion snaps/features/static-files.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Include and retrieve static files in the Snap bundle.
sidebar_position: 11
sidebar_position: 12
---

# Static files
Expand Down
2 changes: 1 addition & 1 deletion snaps/how-to/debug-a-snap/common-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Now you can make changes to your dependencies inside `node_modules` and run
This creates a `.patch` file containing your dependency patch.
These patches can be committed to your Git repository and are replayed when you re-install your dependencies.

### Patch the use of XMLHttpRequest
### Patch the use of `XMLHttpRequest`

The `XMLHttpRequest` API is not exposed in the Snaps execution environment and won't be in the future.
Because of this, you may run into issues with dependencies in your dependency tree attempting to
Expand Down
4 changes: 2 additions & 2 deletions snaps/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ The following Snaps features are available in the stable version of MetaMask:
},
{
icon: require("./assets/features/network.png").default,
href: "reference/permissions#endowmentnetwork-access",
href: "features/network-access",
title: "Network access",
description: <>Make API calls using <code>fetch()</code>.</>
description: <>Access the internet using the <code>fetch</code> function.</>
},
{
icon: require("./assets/features/locale.png").default,
Expand Down
15 changes: 0 additions & 15 deletions snaps/reference/permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,6 @@ domain resolution is happening on Ethereum Mainnet.
To access the internet, a Snap must request the `endowment:network-access` permission.
This permission exposes the global `fetch` API to the Snaps execution environment.

:::caution
`XMLHttpRequest` isn't available in Snaps, and you should replace it with `fetch`.
If your dependencies use `XMLHttpRequest`, you can
[patch it away](../how-to/debug-a-snap/common-issues.md#patch-the-use-of-xmlhttprequest).
:::

Specify this permission in the manifest file as follows:

```json title="snap.manifest.json"
Expand All @@ -213,15 +207,6 @@ Specify this permission in the manifest file as follows:
}
```

#### Same-origin policy and CORS

`fetch()` requests in a Snap are bound by the browser's [same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#cross-origin_network_access).
Since Snap code is executed in an iframe with the `sandbox` property, the browser sends an `Origin`
header with the value `null` with outgoing requests.
For the Snap to be able to read the response, the server must send an
[`Access-Control-Allow-Origin`](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) CORS header
with the value `*` or `null` in the response.

### `endowment:rpc`

To handle arbitrary JSON-RPC requests, a Snap must request the `endowment:rpc` permission.
Expand Down

0 comments on commit feee275

Please sign in to comment.