> ## Documentation Index
> Fetch the complete documentation index at: https://chainpatrol.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallet Developer Integration Guide

> In this guide, you'll learn how to integrate ChainPatrol API into your wallet.

<Note>
  This guide assumes you're creating a wallet using a web browser extension, but the same principles apply
  to integrate our APIs for Mobile or Desktop wallets.

  [Let us know](mailto:support@chainpatrol.io) if you'd like to see a guide for a specific
  use-case that's not covered here.
</Note>

## Overview

The goal of integrating ChainPatrol's API into your wallet is to prevent users from interacting
with a malicious website that is intended to steal their funds or credentials.

To achieve this goal, you will need to do the following:

* 🔍 Detect when a user has visited a new website
* 🥷 Check if the website is malicious with the ChainPatrol API
* ⚠️ Display a warning to the user if the website is malicious
* 🤞 Allow the user to continue if they wish
* 😅 Allow the user to report a false positive

Let's dive deeper into each of these steps:

## Detecting navigation to a new website

<Note>
  In the code examples below, we're using Mozilla's
  [webextension-polyfill](https://github.com/mozilla/webextension-polyfill) to
  smooth out the differences between the Chrome and Firefox APIs.
</Note>

The first step is to detect when a user has visited a new website. If you're building a
web browser extension, you have a couple of choices:

### (Recommended) Option 1: Use the `browser.onBeforeNavigate` API

This approach requires adding the `webNavigation` permission to your `manifest.json` file:

```json theme={null}
{
  "permissions": ["webNavigation"]
}
```

<Warning>
  If your extension does not already have this permission, this will trigger a new
  permissions request when the user installs/updates your extension to "Read your browsing history".

  Alternatively, you can make this permission optional and request it at runtime to avoid
  disabling your extension for users who don't want to grant this permission. Read more
  about optional permissions [here](https://developer.chrome.com/docs/extensions/reference/permissions/#overview).
</Warning>

Then you can listen for the `onBeforeNavigate` event in your Background script:

```ts theme={null}
import browser from "webextension-polyfill";

browser.webNavigation.onBeforeNavigate.addListener(async function (details) {
  // Filter out subframes and any navigation events that don't have a URL
  if (details.frameId !== 0 || !details.url) {
    return;
  }

  // ...
});
```

### Option 2: Use the `browser.tabs.onUpdated` API

This approach requires adding the `tabs` permission to your `manifest.json`:

```json theme={null}
{
  "permissions": ["tabs"]
}
```

<Warning>
  If your extension does not already have this permission, this will trigger a new
  permissions request when the user installs/updates your extension to "Read your browsing history".

  Alternatively, you can make this permission optional and request it at runtime to avoid
  disabling your extension for users who don't want to grant this permission. Read more
  about optional permissions [here](https://developer.chrome.com/docs/extensions/reference/permissions/#overview).
</Warning>

Then you can listen for the `onUpdated` event in your Background script:

```ts theme={null}
import browser from "webextension-polyfill";

browser.tabs.onUpdated.addListener(async function (tabId, changeInfo, tab) {
  // Filter out any tab change events that aren't complete, aren't for the
  // active tab, or tabs that don't have a URL
  if (changeInfo.status !== "complete" || !tab.active || !tab.url) {
    return;
  }

  // ...
});
```

### Option 3: Get the current URL from a content script

This option assumes you already have a content script that runs on every page, ie. you have
something like this in your `manifest.json`:

```json theme={null}
{
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}
```

<Warning>
  If your extension does not already have this permission, this will trigger a new
  permissions request when the user installs your extension to "Read and change all your
  data on all websites".

  This is a very broad permission, and the warning message may scare some users away if
  you don't already have this permission. For this reason, we recommend using one of the
  other options above if possible. But if you need to use this option, you can make this
  permission optional and inject the content script at runtime. Read more about this approach
  [here](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#programmatic).
</Warning>

If you're already using a content script in your extension, you can get the current
URL from the `window.location` object without needing to add any additional permissions.

```ts theme={null}
const url = window.location.href;
```

You can read this value at any time, but we recommend reading it either when the page
first loads, or when the user attempts to initiate a transaction in your wallet app.

You'll need to send this URL to your background script so that it can check if the
website is malicious. This can be done using message passing:

```ts theme={null}
// content.js
const url = window.location.href;

// send the URL to the background script
browser.runtime.sendMessage({ type: "CHAINPATROL_CHECK_URL", url });
```

```ts theme={null}
// background.js

// listen for the message from the content script
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === "CHAINPATROL_CHECK_URL") {
    // do something with request.url
  }
});
```

## Checking if the website is malicious

Once we know the user has visited a new website, we can check if the website is malicious
with the ChainPatrol API.

```ts theme={null}
// check if a URL is blocked
export const checkUrl = async (url: string) => {
  const response = await fetch(
    "https://app.chainpatrol.io/api/v2/asset/check",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-KEY": "YOUR API KEY",
      },
      body: JSON.stringify({ type: "URL", content: url }),
    }
  );

  const data = await response.json();

  return data.status === "BLOCKED";
};
```

## Displaying a warning to the user

If the website is malicious, you should display a warning to the user.

Our recommended approach is to redirect the user to a warning page which will let the
user know that they are about to visit a malicious website, and give them the option to
safely exit, continue, or report a false positive if they believe the website is not malicious.

There are two options for creating the warning page:

<AccordionGroup>
  <Accordion title="ChainPatrol's Hosted Page" description="Recommended option" icon="sparkles" iconType="duotone">
    ## ChainPatrol hosted Page

    ![Warning Page](https://user-images.githubusercontent.com/10101970/219275077-4eda587c-075e-4c61-aa39-ec2802b6613b.png)

    The ChainPatrol hosted page takes care of:

    * Displaying a warning to the user
    * Allowing the user to continue if they wish
    * Allowing the user to report a false positive

    ### Using the warning page

    When you have determined that the site is malicious, you can redirect the tab to the ChainPatrol warning page. You need to pass the `originUrl` query parameter to the warning page so that it can display the URL to the user.

    ```ts theme={null}
    browser.webNavigation.onBeforeNavigate.addListener(async function (details) {
      const isBlocked = await checkUrl(details.url);
      if (isBlocked) {
        // redirect
        browser.tabs.update(details.tabId, {
          url: `https://app.chainpatrol.io/warning?originUrl=${details.url}`,
        });
      }
    });
    ```

    ### Allowing the user to Continue

    To allow the user to ignore the warning and continue to the potentially malicious site, listen for the `CHAINPATROL_CONTINUE_AT_OWN_RISK` message in your background script
    and add the domain to a list of domains to ignore.

    ```ts theme={null}
    // In your extension's background script
    browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
      if (request.type === "CHAINPATROL_CONTINUE_AT_OWN_RISK") {
        addToIgnoreList(request.domain);
      }
    });
    ```

    Then you can update your code to first check if the URL is in the ignore list before checking if it's blocked:

    ```ts theme={null}
    browser.webNavigation.onBeforeNavigate.addListener(async function (details) {
      // exit early if the URL is in the ignore list
      if (checkIgnoreList(details.url)) {
        return;
      }

      const isBlocked = await checkUrl(details.url);
      if (isBlocked) {
        // redirect
        browser.tabs.update(details.tabId, {
          url: `https://app.chainpatrol.io/warning?originUrl=${details.url}`,
        });
      }
    });
    ```

    <Note>
      It's up to you how you want to store this data, but we recommended using the
      browser's storage APIs, such as:
      [chrome.storage](https://developer.chrome.com/docs/extensions/reference/storage/)
      for Chrome extensions.
    </Note>

    ### Whitelabeling the warning page

    If you want to customize the look and feel of the warning page, [reach out to us](mailto:nikita@chainpatrol.io?subject=Whitelabelling%20warning%20page\&body=)
    and we can work with you to create a custom branded warning page with your logo and colors.
  </Accordion>

  <Accordion title="Custom Page" description="Use if you want full control/branding" icon="brackets-curly" iconType="duotone">
    ## Custom Page

    ### Displaying the warning

    We can display the warning by reading the `originUrl` query parameter:

    ```js theme={null}
    const urlParams = new URLSearchParams(window.location.search);
    const originUrl = urlParams.get("originUrl");
    ```

    and displaying it on the page.

    ```html theme={null}
    <h1>Warning</h1>
    <p>
      You are about to visit a website that has been flagged as malicious by
      ChainPatrol.
    </p>
    <p><strong>Origin URL:</strong> {{ originUrl }}</p>
    ```

    ### Allowing the user to Continue

    If the user wishes to continue, we can allow them to do so by adding a button to the warning page that will redirect them
    back to the original website

    ```html theme={null}
    <a href="{{ originUrl }}">Continue at your own risk</a>
    ```

    <Note>
      To prevent the user from seeing the warning again, we can add the domain to a
      list of domains to ignore. It's up to you how you want to store this data, but
      we recommended using the browser's storage APIs or equivalent on other
      platforms.
    </Note>

    #### Allowing the user to report a false positive

    If the user believes the website is not malicious, we can allow them to report a false positive
    by adding a button to the warning page that will redirect them to the [ChainPatrol dispute page](https://app.chainpatrol.io/dispute).

    ```html theme={null}
    <a href="https://app.chainpatrol.io/dispute?content={{ originUrl }}">
      Report a false positive
    </a>
    ```
  </Accordion>
</AccordionGroup>

If you need help deciding which option is best for you, please feel free to reach out to us.

## Conclusion

We've now added a layer of security to your wallet by protecting users from scams and phishing.

## Next Steps

* Read the [ChainPatrol API Documentation](/docs/api)
