# ChainPatrol Discord Bot Source: https://chainpatrol.io/docs/bots/discord-bot A Discord bot that can be used submit scam reports to ChainPatrol ![ChainPatrol Discord Bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot.png) If you have a **Discord server**, you can use the [ChainPatrol Discord bot](https://chainpatrol.io/bot) to let your server members submit scam reports to **ChainPatrol**. The bot will generate new reports that get sent to your admin dashboard for review. ## Setup If you have a dedicated `scam-reports` channel, we recommend pinning a message in this channel and directing your server members to use the bot there for easy reporting ### Install the bot To add the bot to your server, you need to be an admin of the server. Then, you can use the following link to add the bot: [🚀 Add ChainPatrol to your server](https://chainpatrol.io/bot/install) Next, you need to configure the bot to send reports to your admin dashboard on ChainPatrol. Right now, this is can be done by reaching out to us [via email](mailto:support@chainpatrol.io?subject=%5BDiscord%20Bot%5D%20Setup%20integration%20with%20ChainPatrol\&body=Hi,%20I%20would%20like%20to%20link%20the%20Discord%20bot%20to%20my%20ChainPatrol%20account%20as%20described%20here:%20https://chainpatrol.io/docs/general/discord-bot.%0A%0AThanks!) and letting us know that you want to add the bot to your server. We will create an organization for you on ChainPatrol and you can then use the `/setup connect` slash command to link your Discord server to your organization on ChainPatrol. To check that the bot is working, you can use the `/setup status` command to see if the bot is connected to your ChainPatrol organization. ## Features ### Scam Reports The bot allows server members to submit scam reports directly to ChainPatrol. #### Usage Once the bot is added to your server, you can use the following commands: * `/report ` - Submit a scam report for the given URL * `/check ` - Check if the given URL is a scam #### Example Here is an example of how to use the bot to submit a scam report: ![Example of using the ChainPatrol Discord bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-prompt.png) ![Loading of the ChainPatrol Discord bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-loading.png) ![Success of the ChainPatrol Discord bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-success.png) ### Reports Feed You can create a feed channel of all reports to your organization. This feature allows you to see all scam reports submitted through the bot in a dedicated channel. #### Setup 1. Create a new channel on your Discord server and name it something like `chainpatrol-reports` 2. Use the following command to link the channel to your ChainPatrol organization: ``` /setup feed ``` 3. Follow the instructions in the bot's response to link the channel to your ChainPatrol organization ![Image showing the Discord bot's response to the setup feed command](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-feed-setup.png) You can check that the feed is connected correctly by running the `/setup status` command. If the feed is connected correctly, you should see the channel name in the bot's response. ![Image showing the Discord bot's response to the setup status command after setting up the feed](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-feed-status.png) As a final test, you can try submitting a test scam report using the `/report` command. You should see a message in the feed channel with the scam report shortly after submitting. ![Example of the feed channel](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-feed.png) ### Link Monitoring ChainPatrol can monitor your Discord channels for suspicious links and automatically take action when they are detected. This feature helps protect your community from scams and malicious content. #### Setup To enable link monitoring in a channel: 1. Navigate to the channel you want to monitor 2. Run the `/setup linkmonitoring` command 3. Confirm the setup when prompted Only server administrators or users with "Manage Server" permissions can enable link monitoring #### How it Works Once enabled, ChainPatrol will: 1. Monitor all messages in the configured channel for URLs 2. Check each URL against ChainPatrol's comprehensive blocklist, which includes: * Known scam websites * Phishing attempts * Malicious domains * Other security threats reported to ChainPatrol 3. Take action based on your server's configuration when suspicious links are detected The blocklist is continuously updated with new threats reported by the ChainPatrol community and security researchers. You can [search through our blocklist](https://app.chainpatrol.io/search) to see what threats we're protecting against. #### Response Actions When a suspicious link is detected, ChainPatrol can be configured to: * **React with 🚨** - Adds a warning reaction to the message * **Delete the message** - Automatically removes the message * **Notify moderators** - Sends an alert to your moderator channel The response action is configured by your server administrator through the ChainPatrol dashboard #### Example Here's what happens when a suspicious link is detected: ![Example of link monitoring in action](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-bot-link-monitoring.png) ## Common Issues ![no-response](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-application-no-response.png) ### Custom Elevated Permissions * Bot role may need elevated permission to interact with private channels * If you are adding the bot to a channel that is not normally visible to `@everyone`, then you will need to Slash commands not visible to Discord members ![Kebab Menu](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-private-channel.png) ![Report Modal](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-select-app.png) * Embed links permissions are required for your reports feed ![channel embeds](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-channel-embed-links.png) * Make application commands available to users * Server members will not be able to use the ChainPatrol bot commands if they do not have access to application commands ![application commands](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-application-comands.png) ## Debugging Tips ### View Server As Role * You can right click the ChainPatrol role in server settings to see the server as the bot role ![view as role](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/discord-view-as-role.png) Trying to access a feature in an inaccessible part of the server will lead to an error. Make sure the bot's permissions can see and interact with what you are debugging. Check out [Discord's Role Management 101](https://support.discord.com/hc/en-us/articles/214836687-Role-Management-101) Article for additional help! ## Privacy The bot does not collect any personal information. It only collects the URL and the Discord ID for the user that submitted the report (in case a moderator needs more information about why the URL is a scam). The bot does not store any information about the server it is added to. ## Source Code The source code for the bot is available on GitHub: [chainpatrol/discord-bot](https://github.com/chainPatrol/discord-bot) # ChainPatrol Slack Bot Source: https://chainpatrol.io/docs/bots/slack-bot A Slack bot that can be used to submit scam reports to ChainPatrol If you have a **Slack workspace**, you can use the ChainPatrol Slack Bot to let your workspace members submit scam reports to **ChainPatrol**. The bot will generate new reports that get sent to your admin dashboard for review. ## Setup ### Bot Installation Start by opening your dashboard on the [ChainPatrol app](https://app.chainpatrol.io/). ![Step 1 - Dashboard](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/dashboard-navbar.png) In the navbar, select **Settings** to go to your **Organization Settings** page. ![Step 2 - Organization Settings](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/organization-settings.png) Once you are in the organization settings, navigate to the **Integrations** tab. This section contains options for the Slack bot as well as other integrations. ![Step 3 - Integrations Tab](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/settings-integrations.png) In the Integrations tab, you will find an option to **Add to Slack**. Click this button, then you will be redirected to the Slack authorization page. Click **Allow**. ![Step 4 - Add Bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/slack-integration-authorization.png) Remember to select the correct workspace at the top right of the authorization page. **Important**: Please avoid using organization-level installs for the ChainPatrol Slack Bot. Organization-level and enterprise installs can cause issues with the bot's functionality and may not properly integrate with your ChainPatrol dashboard. Always use workspace-level installations to ensure proper operation. ## Confirmation and Finalization The ChainPatrol Slack Bot should appear in your listed apps along with other allowed workspace apps. ![Slack Apps](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/slack-apps.png) ### Adding ChainPatrol Bot To Your Reporting Channel Remember to add the slack bot to the reporting channel! By default, the ChainPatrol bot does not automaically read and join existing channels for privacy. ![Kebab Menu](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/slack-channel-details.png) ![Report Modal](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/slack-add-bot.png) ![Report Modal](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/slack-select-bot.png) ### Link Organization This step needs to be done with help from ChainPatrol staff in order for the Slack Bot to work properly. **Please send ChainPatrol staff your workspace's Slack Team ID so that we can finish the automated pipeline.** * Follow [Slack's documentation](https://slack.com/intl/en-gb/help/articles/221769328-Locate-your-Slack-URL-or-ID#free,-pro-and-business+-subscriptions-2) to locate your Team ID. Slack refers to the Team ID as "workspace or org ID". `https://app.slack.com/client/TXXXXXXX/CXXXXXXX` In the above URL, the Team ID is the slug that begins with `T`. ## Usage Once the bot is added to your workspace and you have **sent ChainPatrol your Team ID**, you can use the following actions: ### Slash Commands * `/chainpatrol ` - Submit a scam report for the given URL ### Shortcut Actions For a given message, click on the kebab menu and then select the `Create Report` option. ![Kebab Menu](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/slack-kebab.png) ![Report Modal](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/report-modal.png) ## Privacy The bot does not collect any personal information. It only collects the URL and the Slack ID of the user that submitted the report (in case a moderator needs more information about why the URL is a scam). The bot does not store any sensitive information about the workspace it is added to. # ChainPatrol Telegram Bot Source: https://chainpatrol.io/docs/bots/telegram-bot A Telegram bot that can be used to submit scam reports to ChainPatrol If you have a **Telegram group**, you can use the ChainPatrol Telegram Bot to let your group members submit scam reports to **ChainPatrol**. The bot will generate new reports that get sent to your admin dashboard for review. ## Setup ### Bot Installation **Beware of impersonators!** The official ChainPatrol Telegram bot is `@ChainPatrol_Bot`. If you see any other bot claiming to be the ChainPatrol bot, please report it to us. Start by adding the ChainPatrol Telegram Bot to your group chat. You can find the bot by searching for its username in Telegram. ![Step 1 - Add Bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-bot-add.png) Once the bot is added to your group chat, use the `/help` command to see the available commands. ![Step 2 - Setup Connect](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-commands.png) ### Bot Configuration ![Confirmation Message](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-setupstatus.png) Visit your [ChainPatrol Dashboard](https://app.chainpatrol.io/admin) and go to the **settings** page. If you don't have a ChainPatrol account and want to protect your community, reach out to us directly! ![Step 1 - Add Bot](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-bot-settings.png) Go to the **Integrations** on the left sidebar. ![Step 2 - Integrations](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-bot-integrations.png) Click on "Add New Telegram Group" and configure the group details. ![Step 2 - Add details](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-bot-integration-details.png) ## Usage Use the `/setupconnect` command to confirm the connection between your group and ChainPatrol. Once the bot is added to your group and the connection process is complete, you can use the following commands: ### Commands * `/report ` - Submit a scam report for the given URL with a brief description of why it's suspicious * `/check ` - Check if a URL is on the block list * `/setupstatus` - Find out if this chat group is associated with an organization * `/setupconnect` - Generates the URL to link Telegram group to organization * `/help` - Display a list of available commands and their descriptions ## Features ### Auto-Link Monitoring The ChainPatrol Telegram Bot automatically monitors all links shared in your group chat. This feature provides an additional layer of protection for your community: * **Real-time Scanning**: Every link posted in the group is instantly checked against ChainPatrol's extensive database of known scams and malicious URLs. * **Automatic Alerts**: If a potentially harmful link is detected, the bot immediately notifies the group, warning members about the potential risk. * **Proactive Protection**: This feature helps prevent scams before they can affect your community members, even if no moderators are actively monitoring the group. ![Auto-Link Monitoring](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/telegram-auto-link-monitoring.png) ## Privacy The bot does not collect any personal information. It only collects the URL and the Telegram ID of the user that submitted the report (in case a moderator needs more information about why the URL is a scam). The bot does not store any sensitive information about the group it is added to. The ChainPatrol Telegram bot is like any group user. You can adjust permissions according to your group's needs. # Asset Changelog Source: https://chainpatrol.io/docs/external-api/asset-changelog POST /asset/changelog Asset changelog. Assets can be changed for various reasons, such as false positives, false negatives or normal reviews. # Asset Check Source: https://chainpatrol.io/docs/external-api/asset-check POST /asset/check Check asset status # Asset Details Source: https://chainpatrol.io/docs/external-api/asset-details POST /asset/details Get Asset Details # Asset List Source: https://chainpatrol.io/docs/external-api/asset-list POST /asset/list List asset statuses The `/asset/list` API will soon require an API Key, whereas previously this API was usable without an API Key. Please double check you are using a ChainPatrol issued API key. We've recently updated this endpoint to support pagination. If you encounter errors related to payload size, please consider using the pagination feature as described below. ## Pagination To use pagination, include the `per_page` and `next_page` parameters in your request: * `per_page `: Number of items to return per page (max: 10000) * `next_page `: Cursor for the next page of results ### Example implementation for pagination: ```javascript JavaScript async function fetchAllAssets(type, status) { let allAssets = []; let nextPage = null; while (true) { const response = await fetch( "https://app.chainpatrol.io/api/v2/asset/list", { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": "YOUR_API_KEY_HERE", }, body: JSON.stringify({ type, status, per_page: 500, next_page: nextPage, }), } ); const data = await response.json(); allAssets = allAssets.concat(data.assets); nextPage = data.next_page; if (!nextPage) { break; } } return allAssets; } fetchAllAssets("URL", "BLOCKED") .then((assets) => console.log("All assets:", assets)) .catch((error) => console.error("Error fetching assets:", error)); ``` ```typescript TypeScript async function fetchAllAssets(type: string, status: string): Promise { let allAssets: any[] = []; let nextPage: string | null = null; while (true) { const response = await fetch( "https://app.chainpatrol.io/api/v2/asset/list", { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": "YOUR_API_KEY_HERE", }, body: JSON.stringify({ type, status, per_page: 500, next_page: nextPage, }), } ); const data = await response.json(); allAssets = allAssets.concat(data.assets); nextPage = data.next_page; if (!nextPage) { break; } } return allAssets; } fetchAllAssets("URL", "BLOCKED") .then((assets) => console.log("All assets:", assets)) .catch((error) => console.error("Error fetching assets:", error)); ``` ```python Python import requests def fetch_all_assets(type: str, status: str) -> list: all_assets = [] next_page = None while True: response = requests.post( "https://app.chainpatrol.io/api/v2/asset/list", headers={ "Content-Type": "application/json", "X-API-KEY": "YOUR_API_KEY_HERE", }, json={ "type": type, "status": status, "per_page": 500, "next_page": next_page, }, ) data = response.json() all_assets.extend(data["assets"]) next_page = data.get("next_page") if not next_page: break return all_assets try: assets = fetch_all_assets("URL", "BLOCKED") print("All assets:", assets) except Exception as error: print("Error fetching assets:", str(error)) ``` # Asset Submit Source: https://chainpatrol.io/docs/external-api/asset-submit POST /asset/submit Submit a list of assets such as domains, social profiles, or blockchain addresses. Automation will classify and assign them to appropriate organization(s). API Key is Required # Authentication Source: https://chainpatrol.io/docs/external-api/authentication We use **API keys** to authenticate requests. You can get an API key from us by [booking a demo](https://calendar.app.google/mbHSej2xYwa4X9b59). ## How to authenticate a request To authenticate a request, you need to include a `X-API-KEY` header with the value of your API key in your request: ```bash 'X-API-KEY': '' ``` # Get Organization Metrics Source: https://chainpatrol.io/docs/external-api/organization-metrics POST /public/getOrganizationMetrics This API requires an API key with appropriate permissions. Regular organization API keys can only access metrics for their associated organizations. ## Quick Start ### Authentication Include your API key in the `Authorization` header: ```bash Authorization: Bearer your_api_key ``` ### Example Request ```bash curl -X POST 'https://api.chainpatrol.io/public/getOrganizationMetrics' \ -H 'Authorization: Bearer your_api_key' \ -H 'Content-Type: application/json' \ -d '{ "organizationSlugs": ["your-org"], "startDate": "2024-01-01T00:00:00Z", "endDate": "2024-03-01T00:00:00Z" }' ``` ## Example Implementation ```javascript JavaScript async function fetchOrganizationMetrics(organizationSlugs, startDate, endDate) { const response = await fetch( "https://api.chainpatrol.io/public/getOrganizationMetrics", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_API_KEY_HERE", }, body: JSON.stringify({ organizationSlugs, startDate, endDate, }), } ); return response.json(); } // Example usage fetchOrganizationMetrics( ["your-org"], "2024-01-01T00:00:00Z", "2024-03-01T00:00:00Z" ) .then((data) => console.log("Metrics:", data)) .catch((error) => console.error("Error fetching metrics:", error)); ``` ```typescript TypeScript interface OrganizationMetrics { combinedMetrics: { reportsCount: number; threatsBlockedCount: number; threatsBlockedByAssetType: Array<{ assetType: string; count: number; }>; domainsBlockedCount: number; activeThreatsCount: number; totalTakedownsFiledCount: number; totalTakedownsCompletedCount: number; }; perOrgMetrics: { [organizationSlug: string]: { reportsCount: number; threatsBlockedCount: number; threatsBlockedByAssetType: Array<{ assetType: string; count: number; }>; domainsBlockedCount: number; activeThreatsCount: number; totalTakedownsFiledCount: number; totalTakedownsCompletedCount: number; }; }; } async function fetchOrganizationMetrics( organizationSlugs: string[], startDate?: string, endDate?: string ): Promise { const response = await fetch( "https://api.chainpatrol.io/public/getOrganizationMetrics", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_API_KEY_HERE", }, body: JSON.stringify({ organizationSlugs, startDate, endDate, }), } ); return response.json(); } // Example usage fetchOrganizationMetrics( ["your-org"], "2024-01-01T00:00:00Z", "2024-03-01T00:00:00Z" ) .then((data) => console.log("Metrics:", data)) .catch((error) => console.error("Error fetching metrics:", error)); ``` ```python Python import requests from typing import Dict, List, Optional from datetime import datetime def fetch_organization_metrics( organization_slugs: List[str], start_date: Optional[str] = None, end_date: Optional[str] = None ) -> Dict: response = requests.post( "https://api.chainpatrol.io/public/getOrganizationMetrics", headers={ "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY_HERE", }, json={ "organizationSlugs": organization_slugs, "startDate": start_date, "endDate": end_date, }, ) return response.json() # Example usage try: metrics = fetch_organization_metrics( ["your-org"], "2024-01-01T00:00:00Z", "2024-03-01T00:00:00Z" ) print("Metrics:", metrics) except Exception as error: print("Error fetching metrics:", str(error)) ``` ## API Details ### Request Parameters | Parameter | Type | Required | Description | | ----------------- | --------- | -------- | -------------------------------------------- | | organizationSlugs | string\[] | Yes | Array of organization slugs to query | | startDate | Date | No | Start date for metrics (default: all time) | | endDate | Date | No | End date for metrics (default: current date) | ### Response Format ```typescript { combinedMetrics: { reportsCount: number; // Total number of reports threatsBlockedCount: number; // Total number of threats blocked threatsBlockedByAssetType: Array<{ // Threats blocked grouped by asset type assetType: string; count: number; }>; domainsBlockedCount: number; // Number of domains blocked activeThreatsCount: number; // Number of active threats totalTakedownsFiledCount: number; // Total number of takedowns filed totalTakedownsCompletedCount: number; // Total number of completed takedowns }; perOrgMetrics: { // Same metrics as above, but per organization [organizationSlug: string]: { reportsCount: number; threatsBlockedCount: number; threatsBlockedByAssetType: Array<{ assetType: string; count: number; }>; domainsBlockedCount: number; activeThreatsCount: number; totalTakedownsFiledCount: number; totalTakedownsCompletedCount: number; }; }; } ``` ## Error Handling | Status Code | Description | | ------------------------- | --------------------------------------------------------------------- | | 401 Unauthorized | Invalid or missing API key | | 403 Forbidden | API key does not have permission to query the requested organizations | | 500 Internal Server Error | Server error occurred while processing the request | ## Notes * If no date range is provided, metrics will be returned for all time * The response includes both combined metrics across all requested organizations and per-organization breakdowns * Special organization API keys (Sui, Consensys) can query metrics for any organization * Regular organization API keys can only query their own organization's metrics # API Overview Source: https://chainpatrol.io/docs/external-api/overview We work with leading wallets and security to block scam links, contract addresses, and wallet addresses before a user interacts with the scam. ChainPatrol's APIs are offered as a free service to wallets, security apps, and marketplaces. File a report against a scam. Fetch the latest changes to our allowlist/blocklist. Check if an asset is allowed or blocked. Fetch our entire allowlist/blocklist for use in your own application. # Report Create Source: https://chainpatrol.io/docs/external-api/report-create POST /report/create Create a new report on ChainPatrol for a particular organization # Get Your API Key Source: https://chainpatrol.io/docs/general/api-key Learn how to obtain and use your ChainPatrol API key ## Getting Your API Key To access ChainPatrol's APIs and services, you'll need an API key. Here's how to get one: 1. Go to your [Organization Dashboard](https://app.chainpatrol.io/admin) 2. Navigate to the organization's `settings` page 3. Navigate to `API keys` 4. Click on `Create Key` and pick your settings ## Types of API Keys ### Organization vs User Keys * **Organization Keys**: Grant organization-level attribution * Reports submitted with organization keys are attributed to a machine user * Best for automated systems, integrations, and organization-level workflows * Ideal for bots, automated reporting systems, and CI/CD pipelines * **User Keys**: Grant user-level attribution * Reports submitted with user keys are attributed directly to your user account * Best for personal use and when individual accountability is needed * Ideal for manual reporting and personal tooling ### Test vs Live Keys ChainPatrol provides both test and live environments to help you develop and test your integration safely. * **Test Keys**: For distinguishing when being used in development and testing * Use in development environments * **These keys still affect production data** * **Live Keys**: For production use * Use in production environments * Affects real data and reports * Required for actual threat detection and reporting ## API Key Format ChainPatrol API keys follow this format: * Always start with the prefix `cp_` * Are unique to your organization * Should be kept secure and not shared publicly ## Using Your API Key When making API requests to ChainPatrol, include your API key in the request headers: ```typescript 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: "example.com", }), }); ``` ## Support If you need help with your API key or have any questions, you can: * Email us at [engineering@chainpatrol.io](mailto:engineering@chainpatrol.io) * Visit our [documentation](/external-api/overview) for more information about our APIs # Concepts Source: https://chainpatrol.io/docs/general/concepts ## Assets On ChainPatrol, we track crypto-related items like URLs, contract addresses, and wallet addresses. These items are called **assets**. Assets can be added to the ChainPatrol database by organization owners. Typically, we'll add the assets for you during your onboarding process. ![Assets](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/assets.png) ### Asset Status Each asset has a status that indicates whether or not it is allowed or blocked: * **Allowed** - The asset is safe and has been reviewed by the owner of the asset and ChainPatrol. * **Blocked** - The asset is a scam and has been reported to ChainPatrol. If the asset has not been reviewed by ChainPatrol, it will have the following status: * **Unknown** - The asset has not been reviewed by ChainPatrol. ## Detections Detections are potential malicious activities that have been automatically identified by our system. Our automated detection system continuously monitors various platforms and networks to identify potential threats and suspicious activities related to your assets. ## Reports Reports are submissions of potential scams or threats made by users or automated systems. They are the way that users can change the status of an asset. When a user reports an asset, they submit one or more proposals that contain a request to change the asset status. Reports can be submitted either by the org members through the organization's admin dashboard, or by the public through the organization's public security portal. ### Report Status Each report has a status that indicates whether or not it has been reviewed by the organization owner and ChainPatrol: * **To Do**: None of the proposals in the report have been reviewed yet * **In Progress**: Some of the proposals in the report have been reviewed * **Closed**: All of the proposals in the report have been reviewed Reports are grouped by their status in the admin dashboard to make it easier to manage. For more information about how to create reports, see the [Report stage](/reporting-flow/report) page. ![Report Statuses](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/report-statuses.png) ## Proposals & Asset Scans Proposals are the way that users can propose changes the status of an asset. When a user submits a report, they are actually submitting one or more proposals. Typically, a scam will have multiple URLs and contract addresses associated with it, so you can submit a report with separate proposals for each with some context about why you think it's a scam in the description. Asset scans are the way that we automatically identify potential threats and suspicious activities related to your assets. ![Proposal](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/proposal.png) ## Reviews Org admins and ChainPatrol staff **both** have to review a proposal to change the status of an asset. When a proposal is reviewed, the reviewer can either approve or reject the proposal. If the proposal is approved by both the org admin and ChainPatrol, the asset status will be updated. If the proposal is rejected by either the org admin or ChainPatrol, the asset status will not be updated, and the proposal will be closed. For more information about how to review proposals, see the [Review stage](/reporting-flow/review) page. ![Review](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/review.png) ## Takedowns Takedowns are requests submitted to remove malicious content from various platforms. When malicious content is identified and confirmed, ChainPatrol can initiate takedown requests to have the content removed. ### Takedown Status Takedowns can have two main states: * **To Do**: The takedown request is to be created. This is the initial state once we have confirmed malicious content. * **In Progress**: The takedown request has been submitted to the platform. ie. We have emailed a hosting provider to remove the malicious content and are waiting for them to respond. * **Completed**: Successfully removed malicious content based on our takedown requests The takedown process helps ensure that confirmed malicious content is removed from platforms, reducing the potential impact on users. # False Positives Source: https://chainpatrol.io/docs/general/false-positives ## Report Click here to file a dispute ## Overview At **ChainPatrol**, we take false positives very seriously. We've seen many projects try to build fully automated systems that are supposed to be 100% accurate, or systems that rely completely on crowd-sourced data, but we've never seen this work out well. Either the system flags too much data as suspicious, or it flags too little. Either the system is too slow to be useful, or it's too fast to be accurate. > Remember the golden rule: **"Garbage in, garbage out."** ### Human in the loop We believe that the only way to build a system that is both accurate and useful, is to have a human in the loop. To that end, we have a team of analysts that review every single report submitted to our platform whether its coming from a Web3 project owner, an automated scan, or from community submission. **An asset will only end up as Blocked in our API if it has been reviewed by a human on our team, or if it has been reviewed by a human working for one of our scanning partners.** That said, accidents can happen. We're human too, and we make mistakes. If you believe that we've made a mistake, please let us know by submitting a dispute. ## Report a false positive You can report a false positive in our API by submitting a dispute at [https://app.chainpatrol.io/dispute.](https://app.chainpatrol.io/dispute.) We will review your dispute as soon as possible, and take the appropriate action. If there's a legal issue involved, you can reach us directly at [nikita@chainpatrol.io](mailto:nikita@chainpatrol.io). # How it works Source: https://chainpatrol.io/docs/general/how-it-works For Web3 project operators, ChainPatrol provides a security portal that allows you to monitor your community for malicious activity. The security portal provides a dashboard that shows you the latest scams targeting your community. You can also whitelist your own links and addresses to prevent false positives. For wallets and security apps, ChainPatrol provides a allow/blocklist of malicious URLs, contract addresses, and wallet addresses through our free API. ![Diagram highlighting the Reporting Flow on ChainPatrol](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/how-it-works.png) # Address Source: https://chainpatrol.io/docs/glossary/asset-types/address Represents a wallet address or smart contract address on the Ethereum blockchain. Addresses are the identifiers of users and smart contracts on the Ethereum blockchain. They are 20 bytes long and are usually represented in hexadecimal form. When submitting a report, you can provide the address of the wallet or smart contract you are reporting on and we'll detect if it's a valid Ethereum address based on the `0x` prefix and the length of the address. ## Normalization We normalize addresses by converting the characters to lowercase. #### Report ``` 0xb3764761e297d6f121e79c32a65829cd1ddb4d32 // Wallet 0x709ecbd07197e082dd830871fec0cc34537a6e23 // Smart contract ``` # Page Source: https://chainpatrol.io/docs/glossary/asset-types/page Represents a page link to be reported The `PAGE` asset type is used to report webpages on a domain. Unlike `URL` asset type, the `PAGE` asset type will NOT normalize the URL string before submitting to **Chainpatrol**. This allows you to report webpages on sites where the scam or malicious content is hosted on a subpath of the domain. When you submit a report, if you submit a URL that matches one of the domains below, a `PAGE` asset will be created instead of a `URL` asset. #### Available page domains ``` bit.ly blur.io goo.gl link3.to linktr.ee opensea.io t.co t.me telegram.me tinyurl.com twitter.com beacons.ai ``` If you would like to see a domain added to this list, please reach out to us at [support@chainpatrol.io](mailto:support@chainpatrol.io?subject=Re:%20New%20domain%20for%20PAGE%20asset%20type\&body=). # URL Source: https://chainpatrol.io/docs/glossary/asset-types/url Represents a domain or subdomain to be reported **URLs** are the most common type of asset. It is a string that is used to identify a resource on the Internet. When you submit a report, if you select asset type as `URL`, the url string will be normalized and its domain will be submitted to **Chainpatrol**. For sites that host user-generated content, such as blogs, forums, and social (ex. Twitter) or link shortening services (ex. Bitly), blocking the domain is not feasible, since it will block all user-generated content. In these cases, you should report using the [PAGE](./page) asset type. ## Normalization Normalization is the process of removing all unnecessary characters from the URL string. It is done to make the URL string more readable and to remove any ambiguity. ChainPatrol performs the following normalization steps: * Remove the scheme (http, https, ftp, etc.) * Convert the domain to lowercase * Convert unicode characters to [punycode](https://en.wikipedia.org/wiki/Punycode) * Remove username, password, port, query, fragment * Remove trailing slash #### Report ``` BLOCK https://www.chainpatrol.xyz/home ``` #### Result When a domain is blocked, all subdomains of that domain are also blocked: ``` BLOCK chainpatrol.xyz BLOCK *.chainpatrol.xyz BLOCK *.*.chainpatrol.xyz ... ``` # Asset Check vs. Asset List Endpoint Source: https://chainpatrol.io/docs/integration/check-vs-list A comparison between the Asset Check and Asset List endpoints and when you should use each one. ## Option 1: Asset Check The [Asset Check](/external-api/asset-check) endpoint allows you to check if a URL is allowed or blocked by ChainPatrol. It's the simplest way to start using ChainPatrol in your wallet since it's a single HTTP request, which avoids the complexities of managing a list of URLs yourself. ### Advantages * **Simple URL checks**: You send an HTTP `POST` request with the actual URLs, and the server responds with the state of the URLs (allowed or blocked). * **Aggregation of data**: The server aggregates data from multiple sources, including ChainPatrol's own database, the [ChainPatrol API](/external-api/), MetaMask's [eth-phishing-detect](https://github.com/MetaMask/eth-phishing-detect), and more. This means that you can check URLs that are not reported to ChainPatrol directly, but are still blocked by ChainPatrol. ### Drawbacks * **Privacy**: URLs are submitted as is to ChainPatrol, so the server knows which URLs you look up. *However*, you can [set up a proxy server](/wallet-integration/proxy) to avoid this. * **Performance**: The server has to look up each URL individually, which can be slow if you have a lot of URLs to check at once or if you check URLs frequently. ## Option 2: Asset List The [Asset List](/external-api/asset-list) endpoint allows you to fetch URLs on our allowlist/blocklist in bulk. This is useful if you want to check a large number of URLs at once, or if you want to keep a local copy of the URLs for privacy or auditing reasons. Using this endpoint requires you to manage your own list of URLs, which can be a bit more complicated. We recommend it only for wallets that have a large number of users and/or specific requirements about data storage and access. ### Advantages * **Privacy**: URLs are not sent to ChainPatrol, so the server doesn't know which URLs you look up. * **Performance**: Although it takes longer to fetch the list, once you have fetched the up-to-date lists, you can check URLs locally without having to send a request to our servers. ### Drawbacks * **Complexity**: You have to manage your own list of URLs, which can be a lot more complicated depending on your requirements around false positives, data storage, and data access. * **Data staleness**: You have to fetch the list of URLs from our servers periodically to ensure that you have the most up-to-date list. If you don't, you may miss new URLs that are added to the list. * **No aggregation**: The asset list endpoint only returns URLs that have been reported to ChainPatrol directly and does not aggregate data from other sources. This means that you may miss URLs that are not reported to ChainPatrol directly, but are still blocked by ChainPatrol. Overall, we recommend using the Asset Check endpoint for most wallets. If you have a large number of users and/or specific requirements around data storage and access, reach out to us and we can help you decide which endpoint is best for you. # Wallet Developer Integration Guide Source: https://chainpatrol.io/docs/integration/guide In this guide, you'll learn how to integrate ChainPatrol API into your wallet. 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:nikita@chainpatrol.io) if you'd like to see a guide for a specific use-case that's not covered here. ## 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 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. 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 { "permissions": ["webNavigation"] } ``` 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). Then you can listen for the `onBeforeNavigate` event in your Background script: ```ts 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 { "permissions": ["tabs"] } ``` 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). Then you can listen for the `onUpdated` event in your Background script: ```ts 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 { "content_scripts": [ { "matches": [""], "js": ["content.js"] } ] } ``` 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). 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 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 // content.js const url = window.location.href; // send the URL to the background script browser.runtime.sendMessage({ type: 'CHAINPATROL_CHECK_URL', url }); ``` ```ts // 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 // 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: ## 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 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 // 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 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}`, }); } }); ``` 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. ### 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. ## Custom Page ### Displaying the warning We can display the warning by reading the `originUrl` query parameter: ```js const urlParams = new URLSearchParams(window.location.search); const originUrl = urlParams.get('originUrl'); ``` and displaying it on the page. ```html

Warning

You are about to visit a website that has been flagged as malicious by ChainPatrol.

Origin URL: {{ originUrl }}

``` ### 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 Continue at your own risk ``` 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. #### 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 Report a false positive ```
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) * Browse the sample [ChainPatrol Extension](https://github.com/chainpatrol/extension) Github Repository # Proxy API requests Source: https://chainpatrol.io/docs/integration/proxy This article explains how to set up a server to proxy requests to ChainPatrol. ## Why proxy requests? There are two main benefits of using a proxy server to route requests to ChainPatrol: 1. **Prevent leaking your API key** - You can proxy requests to ChainPatrol through your own server which adds the ChainPatrol API key to each requests **only on the server**. This way, your API key is never exposed to the public. 2. **Protect your user's privacy** - By proxying requests through your own server, ChainPatrol servers will not be able to read the IP addresses of your users if you are using the `/asset/check` API. This is because the requests to ChainPatrol will originate from your server and not from your user's browser. ## How to proxy requests You can proxy requests to ChainPatrol using any server-side technology. Below are some examples of how to proxy requests using different technologies. The provided examples are just a starting point and do not include any error handling, rate limiting, or request whitelisting. You should implement these features to ensure that your proxy server is secure and reliable. [Cloudflare Workers](https://workers.cloudflare.com/) is a serverless platform that allows you to run JavaScript code on Cloudflare's edge network. This means that you can run your own serverless proxy server for cheap. ### 1. Create a new Cloudflare Worker Go to the [Cloudflare Workers dashboard](https://dash.cloudflare.com/) and create a new worker. ![Create a new Cloudflare Worker](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/cloudflare-workers-1.png) ### 2. Copy and paste the code below Make sure to replace the `API_KEY` variable with your ChainPatrol API key. ```js const API_KEY = 'YOUR_API_KEY'; const UPSTREAM_URL = 'https://app.chainpatrol.io/api/v2/asset/check'; export default { async fetch(request, env, ctx) { // Create a new request to the upstream server const url = new URL(UPSTREAM_URL); const upstreamRequest = new Request(url, request); // Set the ChainPatrol API key upstreamRequest.headers.set('X-API-KEY', API_KEY); // Return the response return fetch(upstreamRequest); }, }; ``` ### 3. Test the proxy server Click on **Save and deploy** and then test the proxy server using `curl`: ```bash curl --request POST \ --url https://chainpatrol-proxy.your-subdomain.workers.dev/ \ --header 'Content-Type: application/json' \ --data '{ "type": "URL", "content": "google.com" }' ``` ```json Output {"status":"ALLOWED"} ``` ### 4. Use the proxy server You can now use the proxy server by sending requests to the URL of your Cloudflare Worker. For example, if your Cloudflare Worker is named `chainpatrol-proxy`, you can send requests to `https://chainpatrol-proxy.your-subdomain.workers.dev`. [Deno Deploy](https://deno.com/deploy) is a serverless platform that allows you to run JavaScript code on Deno's edge network. This means that you can run your own serverless proxy server for cheap. ### 1. Create a new Deno Deploy project Go to the [Deno Deploy dashboard](https://dash.deno.com/) and click on **New project** and fork the `Hello World` example. ![Create a new Deno Deploy project](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/deno-deploy-1.png) ### 2. Copy and paste the code below ```js import { serve } from "https://deno.land/std@0.177.0/http/server.ts"; const UPSTREAM_URL = "https://app.chainpatrol.io/api/v2/asset/check"; async function handler(request: Request): Promise { // Create a new request to the upstream server const url = new URL(UPSTREAM_URL); const upstreamRequest = new Request(url, request); // Set the ChainPatrol API key upstreamRequest.headers.set('X-API-KEY', Deno.env.API_KEY); // Return the response return fetch(upstreamRequest); } serve(handler); ``` ### 3. Set the `API_KEY` environment variable Add the `API_KEY` environment variable in the Deno editor and set your ChainPatrol API key: ### 3. Use the proxy server You can now use the proxy server by sending requests to the URL of your Deno Deploy project. For example, if your Deno Deploy project is named `chainpatrol-proxy`, you can send requests to `https://chainpatrol-proxy.deno.dev`. ## Important Considerations * When deploying your proxy server, consider the ingress and egress volume that you'll handle from your clients. If you're expecting a lot of traffic, you may want to consider using a serverless platform like Cloudflare Workers or Deno Deploy to reduce costs. * Try to keep your proxy server as close to your clients as possible. This will reduce latency and improve performance. * When deploying your proxy server, make sure to use HTTPS. This will ensure that your requests are encrypted and secure. * We reserve the right to block/rate-limit your API key if we detect excessive usage or abuse. Please make sure to handle errors gracefully in the event of unexpected downtime and let us know when you are planning on going live with your integration, so that we can provision the appropriate resources to meet your demand. If you have any questions, please contact us at [support@chainpatrol.io](mailto:support@chainpatrol.io?subject=Re:%20Proxy%20API%20Requests\&body=). # Vercel Integration Source: https://chainpatrol.io/docs/integration/vercel Connect your Vercel team to ChainPatrol to protect your deployments from impersonation ## Overview This guide will help you connect your Vercel team to ChainPatrol. Once connected, ChainPatrol will help protect your Vercel deployments from being impersonated by scammers. ## Steps to Connect ### 1. Access the Integration Page 1. Log in to your ChainPatrol dashboard 2. Navigate to "Settings" in your organization 3. Click on the "Integrations" tab 4. Find the Vercel section and click "Connect to Vercel" ### 2. Authorize with Vercel When you click connect, you'll be redirected to the [Vercel integration page](https://vercel.com/integrations/chainpatrol): 1. Click "Connect Account" 2. Select the Vercel team you want to connect 3. Review the permissions ChainPatrol is requesting 4. Click "Allow Access" to authorize the connection ### 3. Select Your Organization After authorizing with Vercel, you'll return to ChainPatrol where you'll: 1. See a dropdown list of your eligible ChainPatrol organizations 2. Select which organization you want to connect to your Vercel team 3. Click "Connect" to finalize the setup ### 4. Confirmation Once connected, you'll see: * A success message confirming the connection * Your Vercel team ID listed as connected in the integrations page ## What to Expect After Connecting Once connected, ChainPatrol will: * Automatically check against your Vercel deployments for impersonation attempts * Help protect your users from scam sites pretending to be your deployments You can disconnect the integration at any time. ## Need Help? If you encounter any issues during the connection process: * Make sure you have admin permissions in both your Vercel team and ChainPatrol organization * Try refreshing the page and attempting the connection again * Contact ChainPatrol support if you continue to experience issues That's it! Your Vercel deployments are now protected by ChainPatrol. # Webhooks Source: https://chainpatrol.io/docs/integration/webhooks Use webhooks to notify your wallet about changes to ChainPatrol's global blocklist ## What is a webhook? ChainPatrol uses webhooks to notify you about changes to our global blocklist. This allows you to update your blocklist in real-time, without having to wait for a scheduled cron job to run. This is especially useful if you opt to use our [Asset List](/external-api/asset-list) endpoint to sync our data as you can update your blocklist as soon as we update ours. ## Managing Webhooks You can manage your webhooks through the [ChainPatrol dashboard](https://app.chainpatrol.io/admin) under `Settings > Webhooks`. From here you can: 1. Create new webhooks 2. View and monitor webhook deliveries 3. Test webhooks with sample events 4. Enable/disable webhooks 5. Update webhook configurations 6. Delete webhooks Each webhook delivery is logged and can be inspected for debugging purposes, including the full request and response details. ## Event Types ### `debug.test` This event is used for testing your webhook endpoint. It is sent when you click the "Test" button for a webhook in the dashboard. ```json { "event": "debug.test", "created_at": "2023-08-31T00:00:00.000Z", "data": {} } ``` ### `asset.status-updated` This event is sent when the status of an asset changes. The `status` field can be one of `BLOCKED`, `ALLOWED`, or `UNKNOWN`. ```json { "type": "asset.status-updated", "created_at": "2023-08-31T00:00:00.000Z", "data": { "asset_id": 132, "type": "URL", "content": "https://example.com", "status": "BLOCKED" } } ``` ## Webhook Configuration When creating a webhook, you'll need to provide: 1. A HTTPS endpoint URL that will receive the webhook events 2. An optional description to help identify the webhook's purpose 3. Select which events you want to receive (currently only asset.status-updated is available) The webhook secret will be automatically generated and shown to you once when creating the webhook. Make sure to copy it as it won't be displayed again. ## Signature Verification ChainPatrol signs each webhook request with a signature to verify that the request originated from ChainPatrol. The signature is included in the `X-ChainPatrol-Signature` header of each request. The signature is computed by taking the SHA256 HMAC of the request body using your webhook secret as the key. The signature is encoded as a hex string. ``` sha256=hex(hmac_sha256(webhook_secret, request_body)) ``` You can verify the signature of a request by computing the signature yourself and comparing it to the signature included in the request. If the two signatures match, then you can be sure that the request originated from ChainPatrol. Here's an example of how to verify the signature in Node.js: ```js const crypto = require("node:crypto"); const [, signature] = req.headers["x-chainpatrol-signature"].split("="); const expectedSignature = crypto .createHmac("sha256", process.env.WEBHOOK_SECRET) .update(req.body) .digest("hex"); if (signature !== expectedSignature) { throw new Error("Invalid signature"); } ``` ## Delivery Status and Retries Each webhook delivery attempt is logged with one of the following statuses: * `PENDING`: The delivery is queued * `IN_PROGRESS`: The delivery is being attempted * `SUCCESS`: The delivery was successful (received 2xx response) * `FAILURE`: The delivery failed Webhooks will be retried up to 3 times with an exponential backoff if your endpoint returns a non-2xx status code. If your endpoint returns a 2xx status code, then the webhook will not be retried. You can view the delivery status, payload, request, and response details for each webhook attempt in the dashboard. ## Security Webhooks are sent over HTTPS and are signed with a secret that is unique to your account. You should: 1. Only use HTTPS endpoints 2. Keep your webhook secret secure and never commit it to version control 3. Always verify the signature of incoming webhooks 4. Contact us immediately if you suspect your webhook secret has been compromised If you need to rotate your webhook secret, you can delete the existing webhook and create a new one with the same configuration. # Zapier Source: https://chainpatrol.io/docs/integration/zapier Use Zapier to automate your ChainPatrol workflows # ChainPatrol Zapier App Guide Block malicious URLs instantly through Zapier automations. ## Getting Started 1. **Get Your API Key** * Access your ChainPatrol API key from your organization's settings page [Organization Dashboard](https://app.chainpatrol.io/admin) * API key should start with `cp_` 2. **Connect to Zapier** * Use this invite link to access the ChainPatrol Zapier app: [https://zapier.com/developer/public-invite/218319/438734/23848bd6e68c1151aea214acd5f6136d/](https://zapier.com/developer/public-invite/218319/438734/23848bd6e68c1151aea214acd5f6136d/) 3. **Find Your Organization Slug** * This is the identifier in your ChainPatrol URL * Example: If you access ChainPatrol at `app.chainpatrol.io/admin/companyname`, your slug is `companyname` ## Available Actions ### Create Report Creates a new report with URLs to block. #### Input Fields: 1. **URLs to Block** (Required) ``` # Option 1: One URL per line scam1.com scam2.com scam3.com # Option 2: Comma-separated scam1.com, scam2.com, scam3.com ``` * Supports URLs with or without 'https\://' * Can include email addresses and social media handles * Invalid URLs will be skipped 2. **Report Title** (Required) * Example titles: * "Phishing URLs from Discord #security channel" * "Scam websites targeting our users" * "Fake minting sites - Jan 2024" 3. **Additional Details** (Optional) * Add context about the URLs * Suggested details: * Where URLs were found * How they were discovered * Type of scam * Additional evidence 4. **Organization Slug** (Required) * Your ChainPatrol organization identifier ## Common Zap Examples 1. **Discord → ChainPatrol** * Trigger: New message in security channel * Action: Create report with URLs 2. **Google Form → ChainPatrol** * Trigger: New form submission * Action: Create report with submitted URLs 3. **Slack → ChainPatrol** * Trigger: Message with specific emoji reaction * Action: Create report with URLs from message ## Support Need help? Contact [support@chainpatrol.io](mailto:support@chainpatrol.io) # Introduction Source: https://chainpatrol.io/docs/introduction ChainPatrol is the brand protection platform for leading Web3 companies Our mission at ChainPatrol is to protect your community and brand from scammers. * 🖥️ Our 24/7 Monitoring detects scammers targeting your community across X (formerly Twitter), Discord, Telegram, and Google Ads. * 🔐 **ChainPatrol** gets these scams blocked at the wallet level, preventing users from signing malicious transactions. * 🤝 We are working with Metamask and other wallets on a blocklist that warns users when they go to a scam URL or are about to transfer to a scammer's wallet address. ## Getting Started To get started with ChainPatrol, check out any of the following: Learn about our process of reporting scams and getting them blocked Learn about our APIs and how to use them to check for scams Request access to our APIs and get started with our services See what's new in the ChainPatrol app and what we're working on # Constructor Source: https://chainpatrol.io/docs/sdk/chainpatrol-client/constructor Creates a new instance of the `ChainPatrolClient` class. ## Example ```ts import { ChainPatrolClient } from "@chainpatrol/sdk"; const chainpatrol = new ChainPatrolClient({ apiKey: "" }); ``` ## Parameters The `apiKey` property is the API Key for accessing ChainPatrol's APIs. We recommend using an environment variable to store your API Key. The `baseUrl` property is an optional property that specifies the API URL. You only need to specify this if you are using a proxy server. Defaults to `https://app.chainpatrol.io/v2/` # asset.check() Source: https://chainpatrol.io/docs/sdk/chainpatrol-client/instance-methods/asset-check The `asset.check()` method checks the status of an asset. ## Example ```js Code const result = await chainpatrol.asset.check({ type: "URL", content: "https://my-website.scam.com", }); console.log(results); ``` ```js Output { status: "BLOCKED", reason: "eth-phishing-detect" } ``` ## Parameters The `type` property specifies what type of asset you are querying for. The following types are supported: `URL`, `PAGE`, `ADDRESS`. The `content` property contains the actual asset you are querying for. * In the case of a `URL` or `PAGE` asset, this is the URL of the asset. * In the case of an `ADDRESS` asset, this is the wallet or contract address of the asset. ## Return Value The `asset.check()` method returns a `Promise` that resolves to an object with the following properties: The `status` property contains the status of the asset. The following statuses are supported: `UNKNOWN`, `ALLOWED`, `BLOCKED`. If the asset is allowed or blocked, this will be the reason why. ChainPatrol aggregates data from multiple sources, so this will tell you which source blocked or allowed the asset. * `eth-phishing-detect` - the asset is on MetaMask's blocklist * `reported` - the asset is on ChainPatrol's blocklist because it was reported by a user # asset.list() Source: https://chainpatrol.io/docs/sdk/chainpatrol-client/instance-methods/asset-list The `asset.list()` method gets the status of all assets that ChainPatrol has reviewed in bulk. ## Example ```js Code const results = await chainpatrol.asset.list({ type: "URL", status: "BLOCKED", startDate: "2023-01-01", endDate: "2023-12-31", }); console.log(results); ``` ```js Output { assets: [ { type: "URL", content: "example.com", status: "BLOCKED", updatedAt: "2023-01-01T00:00:00.000Z", }, { type: "URL", content: "scam-airdrop.net", status: "BLOCKED", updatedAt: "2023-01-01T00:00:00.000Z", }, ] }; ``` ## Parameters The `type` property specifies what type of asset you are querying for. The following types are supported: `URL`, `PAGE`, `ADDRESS`. The `status` property specifies the status of the asset you are querying for. The following statuses are supported: `BLOCKED`, `ALLOWED`, `UNKNOWN`. The `startDate` property specifies the start date of the time range you are querying for. The date must be in the format `YYYY-MM-DD`. The `endDate` property specifies the end date of the time range you are querying for. The date must be in the format `YYYY-MM-DD`. The `endDate` must be greater than or equal to the `startDate`. ## Return Value The `asset.list()` method returns a `Promise` that resolves to an array of objects with the following properties: The `type` property specifies the type of the asset. The following types are supported: `URL`, `PAGE`, `ADDRESS`. The `content` property contains the content of the asset. * In the case of a `URL` or `PAGE` asset, this is the URL of the asset. * In the case of an `ADDRESS` asset, this is the wallet or contract address of the asset. The `status` property contains the status of the asset. The following statuses are supported: `UNKNOWN`, `ALLOWED`, `BLOCKED`. # Overview Source: https://chainpatrol.io/docs/sdk/chainpatrol-client/overview ChainPatrolClient is used to construct a client that connects to the ChainPatrol API A [ChainPatrolClient](./constructor) allows you to interface with the ChainPatrol API from a Node.js or browser application. ```js import { ChainPatrolClient } from "@chainpatrol/sdk"; const chainpatrol = new ChainPatrolClient({ apiKey: "" }); ``` ## Constructor ### `new ChainPatrolClient()` Creates a new ChainPatrolClient instance. *** ## Instance Methods ### [asset.check()](./instance-methods/asset-check) Checks the status of an asset to see if it is malicious or not. ### [asset.list()](./instance-methods/asset-list) Lists all assets (and their statuses) that have been reviewed by ChainPatrol. # Overview Source: https://chainpatrol.io/docs/sdk/overview Use our JavaScript SDK to interact with ChainPatrol's APIs **Phishing** and **scam URLs** are a huge problem in Web3. To make it easier for wallet and dApp builders to protect their users from these threats, we've built a JavaScript SDK that you can use to interact with our threat detection APIs. ```js import { ThreatDetector } from "@chainpatrol/sdk"; const detector = new ThreatDetector({ mode: "cloud", apiKey: "YOUR_API_KEY", }); const result = await detector.url("https://scam-site.com"); ``` ## Installation ```bash npm install --save @chainpatrol/sdk ``` ```bash yarn add @chainpatrol/sdk ``` ```bash pnpm add @chainpatrol/sdk ``` ## Features Written in TypeScript with full type definitions Works in all modern browsers, Node.js, and browser extensions Minimal dependencies Designed with caching and rate-limiting built-in ## Exports | Name | Description | | :---------------------------------------- | :-------------------------------------------------------------------- | | [ThreatDetector](./threat-detector) | A simple interface for detecting phishing URLs | | [Storage](./storage) | Storage cache implementation for ThreatDetector | | [Relay](./relay) | A message relay for sharing events between browser extension contexts | | [ChainPatrolClient](./chainpatrol-client) | Used to create a client that connects to the ChainPatrol API | export const typescriptIcon = # Quickstart Source: https://chainpatrol.io/docs/sdk/quickstart Get started using the ChainPatrol SDK in your application To use the ChainPatrol SDK, you'll need an API key. You can get one by emailing [support@chainpatrol.io](mailto:support@chainpatrol.io?subject=Re:%20API%20Key%20for%20SDK\&body=Company:%20%0AName:%20%0APurpose:%20). The most common use-case for using the ChainPatrol SDK is to provide scam detection in a browser extension-based wallet (ex. Metamask). The code snippet below shows how to use the SDK in the background script of a browser extension, demonstrating 4 core concepts: * Instantiating the `ThreatDetector` * Listening for navigation events * Using the `ThreatDetector` to check a URL, and redirecting the user if the URL is a scam * Handling events from the warning page using the Relay class to forward events ```js background.js import { ThreatDetector, Relay, Events, Storage } from "@chainpatrol/sdk"; // Instantiate the detector const detector = new ThreatDetector({ mode: "cloud", apiKey: "YOUR_API_KEY", storage: Storage.extension(), }); // Listen for navigation events chrome.webNavigation.onBeforeNavigate.addListener(async ({ url, tabId }) => { const result = await detector.url(url); if (result.ok && result.status === "BLOCKED") { // Redirect the user to the warning page chrome.tabs.update(tabId, { url: result.redirectUrl, }); } }); // Listen for events from the warning page Relay.on(Events.ContinueAtOwnRisk, async ({ domain }) => { await detector.ignore(domain); }); ``` ```js content.js import { Relay, Events } from "@chainpatrol/sdk"; Relay.run([Events.ContinueAtOwnRisk]); ``` ```js warning.js import { Relay, Events } from "@chainpatrol/sdk"; Relay.send(Events.ContinueAtOwnRisk, { domain: "example.com" }); ``` These concepts are generally applicable to other environments as well. For example if you're using the SDK in a messaging web application, instead of listening for navigation events using `chrome.webNavigation`, you would listen for navigation events for links clicked in the application, or you could instead wait until the user initiates a transaction and check the URL that initiated the transaction. The next sections of the documentation will go into more detail about the different classes exported by the SDK, and how to use them. # Overview Source: https://chainpatrol.io/docs/sdk/relay/overview Relay messages between browser extensions and web pages. The `Relay` class is a utility for receiving messages from the ChainPatrol warning page in your browser extension-based wallet/security app. You may already have a message passing system in place in your browser extension, but this class is provided as a convenience for those who do not, or if you want to keep your message passing system separate from the ChainPatrol SDK. ## Usage ```js Warning Page import { Relay, Events } from "@chainpatrol/sdk"; // Send a message to the extension Relay.send(Events.ContinueAtOwnRisk, { domain: "example.com" }); ``` ```js Content Script import { Relay, Events } from "@chainpatrol/sdk"; Relay.run([Events.ContinueAtOwnRisk]); ``` ```js Background Script import { Relay, Events } from "@chainpatrol/sdk"; // Listen for messages from relay Relay.on(Events.ContinueAtOwnRisk, (data) => { // Do something with the event data }); ``` ## How it works In order for events from the warning page to be received by your browser extension, the messages have to be relayed from the warning page to the content script, and then from the content script to the background script. Under the hood, the `Relay` class sets up the appropriate message listeners depending on the scripting context (ie. `window.postMessage` in the warning page, `chrome.runtime.sendMessage` in the content and background scripts), and makes sure that all messages are passed along to all subscribers. *** ## Static Methods ### [send()](./static-methods/send) Sends an event to listeners. ### [run()](./static-methods/run) Sets up listeners for events and forwards events to all other listeners. ### [on()](./static-methods/on) Adds a listener for an event. # on() Source: https://chainpatrol.io/docs/sdk/relay/static-methods/on Listen for events from the ChainPatrol Relay. ## Example ```js import { Relay, Events } from "@chainpatrol/sdk"; Relay.on(Events.ContinueAtOwnRisk, (request) => { // Handle the event }); ``` ## Parameters The `on()` method accepts two parameters: The `type` property specifies what type of event you want to listen for. The `callback` property is a function that will be called when the event is triggered. The event data is passed to the callback function as the first parameter. # run() Source: https://chainpatrol.io/docs/sdk/relay/static-methods/run Starts the relay in the current JS context. ## Example ```js import { Relay, Events } from "@chainpatrol/sdk"; Relay.run([Events.ContinueAtOwnRisk]); ``` ## Parameters The `run()` method accepts one parameter which is an array of events to forward: The `events` property specifies what events to forward to other listeners of the relay. # send() Source: https://chainpatrol.io/docs/sdk/relay/static-methods/send Send an event to the ChainPatrol relay. ## Example ```js import { Relay, Events } from "@chainpatrol/sdk"; Relay.send(Events.ContinueAtOwnRisk, { domain: "example.com" }); ``` ## Parameters The `send()` method accepts two parameters: The `type` property specifies what type of event you want to send. The `data` property is an object that contains the event data. # Browser Source: https://chainpatrol.io/docs/sdk/storage/browser The `Storage.browser()` adapter uses the browser's `localStorage` API to store data. This adapter should be used by dApps that run in the browser. For browser extensions, use the [Storage.extension()](./extension) adapter. ## Example ```js import { Storage } from "@chainpatrol/sdk"; const storage = Storage.browser({ quota: 1024 * 1024 * 2, // 2MB }); ``` ## Limitations The `localStorage` API limits the amount of data that can be stored to 5MB. We recommend using the `quota` option to limit the amount of data that is stored to avoid hitting this limit, especially if you are storing other data in `localStorage` as well. # Extension Source: https://chainpatrol.io/docs/sdk/storage/extension The `Storage.extension()` adapter uses the browser's [extension storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) to store data. Use this adapter if you are building a browser extension for Chrome, Firefox, or Edge. ## Pre-requisites You will need to enable the `storage` permission in your extension's `manifest.json` file: ```json { "permissions": ["storage"] } ``` Optionally, you can also enable the `unlimitedStorage` permission to allow your extension to use more than 5MB of storage. ```json { "permissions": ["storage", "unlimitedStorage"] } ``` ## Example ```js import { Storage } from "@chainpatrol/sdk"; const storage = Storage.extension({ quota: 1024 * 1024 * 5, // 5MB }); ``` # Memory Source: https://chainpatrol.io/docs/sdk/storage/memory The `Storage.memory()` adapter stores data in memory. This is the default adapter when you instantiate a new `ThreatDetector` instance. We don't recommend using this adapter in production, as it will not persist data between sessions. But it is useful for testing and development. ## Example ```js import { Storage } from "@chainpatrol/sdk"; const storage = Storage.memory({ quota: 1024 * 1024 * 2, // 2MB }); ``` # Overview Source: https://chainpatrol.io/docs/sdk/storage/overview Adapters for storing cached data for the Threat Detector The [ThreatDetector](/sdk/threat-detector/overview) class is designed to be used with a cache storage adapter to reduce the number of API calls needed to perform an asset scan. This is done by storing the results of previous API calls in the cache and retrieving them when needed. Depending on what environment you are using the SDK in, you may need to use the appropriate storage adapter. ## Adapters | Adapter | Description | | ------------------------ | -------------------------------------------------------------- | | [Browser](./browser) | Stores the cached data in the browser's local storage. | | [Extension](./extension) | Stores the cached data in the browser's extension storage. | | [Memory](./memory) | Stores the cached data in memory. This is the default adapter. | Are we missing an adapter? Feel free to reach out to us at{" "} [support@chainpatrol.io](mailto:support@chainpatrol.io?subject=Re:%20Custom%20Storage%20Adapter\&body=) and we'll be happy to discuss implementing it. # Constructor Source: https://chainpatrol.io/docs/sdk/threat-detector/constructor ## Modes There are two modes of operation for the Threat Detector: * `local`: This mode uses a local database of scam URLs. Use this mode for offline threat detection and testing. * `cloud`: This mode uses ChainPatrol's cloud service to detect scams. ### Local Mode To use the local mode, you need to instantiate the `ThreatDetector` class with the `mode` option set to `local`. ```js const detector = new ThreatDetector({ mode: "local", }); ``` ### Cloud Mode To use the cloud mode, you need to instantiate the `ThreatDetector` class with the `mode` option set to `cloud` and provide your API key. ```js const detector = new ThreatDetector({ mode: "cloud", apiKey: "YOUR_API_KEY", }); ``` ## Parameters The `mode` property controls the mode of operation for the Threat Detector. The value of this property can be either `local` or `cloud`. The `apiKey` property is the API Key for accessing ChainPatrol's APIs. We recommend using an environment variable to store your API Key. This property is required when the `mode` property is set to `cloud`. If `proxyUrl` is set, this property is not required as the proxy server will handle the authentication. The `proxyUrl` property is an optional property that can be used to specify a proxy URL for accessing ChainPatrol's APIs. This property is useful when you are behind a firewall or need to use a proxy to access the internet. This value is only used when the `mode` property is set to `cloud`. The `redirectUrl` property is an optional property that can be used to specify a redirect URL for when the detector detects a scam. By default, the detector will return the ChainPatrol warning page URL, but you can override this by specifying your own URL. If you specify a **string**, the string will be used as the redirect URL with the scam URL appended as the `originUrl` query parameter: ```js const detector = new ThreatDetector({ redirectUrl: "https://your-warning-page.com/", }); ``` If you specify a **function**, the function will be called with the scam URL as the first argument: ```js const detector = new ThreatDetector({ redirectUrl: (url) => { return `https://your-warning-page.com/?url=${encodeURIComponent(url)}`; }, }); ``` The `storage` property is an optional property that can be used to specify a custom storage adapter for the detector to cache URL lookups. By default, the detector will use the `Storage.memory()` adapter, which stores the cache database in memory. This means that the database will be cleared when the process exits. If you want to persist the database, you can use the `Storage.browser()` adapter, which stores the database in local storage, or the `Storage.extension()` adapter, which stores the database in the browser's extension storage. # allow() Source: https://chainpatrol.io/docs/sdk/threat-detector/instance-methods/allow Use this method to add a domain to the allowlist We recommend only using this method in `local` mode to populate new entries in the allowlist. In `cloud` mode, the allowlist is populated automatically. ## Example ```js Code await detector.allow("google.com"); console.log(await detector.url("https://google.com")); ``` ```js Output { ok: true, url: "google.com", status: "ALLOWED" } ``` ## Parameters The URL to allow. This can be a full URL or a domain. Ex. `https://google.com` or `google.com` ## Return Value The return value is a promise that resolves with a result object. ### Success If the addition was successful, the object will contain the following properties: This property will be `true` if the addition was successful. The `url` property is the URL that was added. ### Failure However, if the addition was unsuccessful, the object will contain the following: This property will be `false` if the addition was unsuccessful. The `url` property is the URL that we tried to add. The `error` property will contain a human-readable error message. # block() Source: https://chainpatrol.io/docs/sdk/threat-detector/instance-methods/block Use this method to add a domain to the blocklist We recommend only using this method in `local` mode to populate new entries in the allowlist. In `cloud` mode, the allowlist is populated automatically. ## Example ```js Code await detector.block("google.com"); console.log(await detector.url("https://google.com")); ``` ```js Output { ok: true, url: "google.com", status: "BLOCKED", redirectUrl: "https://app.chainpatrol.io/warning?originUrl=https://google.com" } ``` ## Parameters The URL to block. This can be a full URL or a domain. Ex. `https://google.com` or `google.com` ## Return Value The return value is a promise that resolves with a result object. ### Success If the addition was successful, the object will contain the following properties: This property will be `true` if the addition was successful. The `url` property is the URL that was added. ### Failure However, if the addition was unsuccessful, the object will contain the following: This property will be `false` if the addition was unsuccessful. The `url` property is the URL that we tried to add. The `error` property will contain a human-readable error message. # ignore() Source: https://chainpatrol.io/docs/sdk/threat-detector/instance-methods/ignore Use this method to ignore a domain when the user chooses to continue at their own risk after seeing a warning If a user chooses to continue at their own risk after seeing a warning, you can use this method to ignore the domain so that the detector ignores the domain in the future. Without this, the user will continue to be redirected to the warning page, which is not a good user experience. ## Example ```js Code await detector.ignore("google.com"); console.log(await detector.url("https://google.com")); ``` ```js Output { ok: true, url: "google.com", status: "IGNORED" } ``` ## Parameters The URL to ignore. This can be a full URL or a domain. Ex. `https://google.com` or `google.com` ## Return Value The return value is a promise that resolves with a result object. ### Success If the addition was successful, the object will contain the following properties: This property will be `true` if the addition was successful. The `url` property is the URL that was added. ### Failure However, if the addition was unsuccessful, the object will contain the following: This property will be `false` if the addition was unsuccessful. The `url` property is the URL that we tried to add. The `error` property will contain a human-readable error message. # url() Source: https://chainpatrol.io/docs/sdk/threat-detector/instance-methods/url Use this method to check a URL to see if it is malicious. Only the domain portion of the URL is checked. The path and query string are stripped before sending the request to the ChainPatrol API to preserve privacy and prevent leaking sensitive information. ## Example ```js Code const result = await detector.url("https://www.mountaintop-finance.com"); console.log(result); ``` ```js Output (Allowed) { ok: true, url: "mountaintop-finance.com", status: "ALLOWED", } ``` ```js Output (Blocked) { ok: true, url: "mountaintop-finance.com", status: "BLOCKED", redirectUrl: "https://app.chainpatrol.io/warning?originUrl=https://www.mountaintop-finance.com" } ``` ```js Output (Error) { ok: false, url: "abcdefgh", error: "Unable to parse domain" } ``` ## Parameters The URL to check. This can be a full URL or a domain. The URL will be parsed to extract only the domain for checking. Ex. `https://google.com` or `google.com` ## Return Value The return value is a promise that resolves with an object containing the result of the check. ### Success If the check was successful, the object will contain the following properties: This property will be `true` if the check was successful. The `url` property is the URL that was checked. The `status` property indicates whether the URL is allowed or blocked. The `redirectUrl` property specifies where to redirect the user when the detector detects a threat. This property will only be present if the `status` property is set to `BLOCKED`. By default, the detector will return the ChainPatrol warning page URL, but you can override this by specifying your own `redirectUrl` in when instantiating the `ThreatDetector`. ### Failure However, if the check was unsuccessful, the object will contain the following: This property will be `false` if the check was unsuccessful. The `url` property is the URL that was checked. The `error` property will contain a human-readable error message. # Overview Source: https://chainpatrol.io/docs/sdk/threat-detector/overview ThreatDetector is used to detect Phishing and Scam websites using ChainPatrol's APIs. A [ThreatDetector](./constructor) allows you to easily build out community safety features in your dApp or wallet. It is a smart wrapper around ChainPatrol's APIs that allows you to check if a website is a scam or not. It comes with a variety of storage adapters, so you can easily cache the results of your checks and avoid making unnecessary API calls. ```js import { ThreatDetector, Storage } from "@chainpatrol/sdk"; // Create a new detector instance const detector = new ThreatDetector({ mode: "cloud", // 'cloud' | 'local' (default: 'cloud') // Optional: Specify a custom API key (only available for 'cloud' mode) apiKey: "YOUR_API_KEY", // Optional: Configure a proxy server (only available for 'cloud' mode) proxyUrl: "https://proxy.acme.com", // Optional: Specify a custom storage adapter storage: Storage.extension(), // storage: Storage.browser(), // storage: Storage.memory(), // Optional: Specify a custom redirect URL redirectUrl: "https://app.chainpatrol.io/warning", }); ``` ## Constructor ### `new ThreatDetector(options)` Creates a new instance of the ThreatDetector class. *** ## Instance Methods ### [url()](./instance-methods/url) Checks if a URL is a scam or not. ### [allow()](./instance-methods/allow) Adds a URL to the local allowlist. ### [block()](./instance-methods/block) Adds a URL to the local blocklist. ### [ignore()](./instance-methods/ignore) Adds a URL to the local ignorelist. # Canary Tokens Source: https://chainpatrol.io/docs/security-integration/canary-tokens Use Canary Tokens to notify ChainPatrol when your website is cloned and have them blocked immediately ## What is a Canary Token? Canary Tokens are a free, open-source tool that helps you discover when bad actors access your data. They can be used to detect unauthorized access to your website, documents, or other sensitive information. You can read more on the [Canary Tokens website](https://docs.canarytokens.org/guide/). ## Cloned Website Tokens Cloned Website Tokens are a type of Canary Token that can be used to detect when your website is cloned. They work by embedding a unique token into your website that is invisible to your users. When a bad actor clones your website, they will also clone the token. When the token is accessed, you will be notified and ChainPatrol will proceed to block and takedown the malicious cloned site. You can read more about Cloned Website Tokens on the [Canary Tokens website](https://docs.canarytokens.org/guide/cloned-web-token.html). ## Setup Instructions Go to the [Canary Tokens Nest](https://canarytokens.org/nest/) and select the `JS cloned website` from the list. Fill the fields with the information below: | Field | Value | | :------------------------------------- | :-------------------------------------------------- | | Domain of protected website | `` | | Mail me here when the alert fires | `` | | Remind me of this when the alert fires | Any note you'd like (ex. `Token for `) | Next, click **Add Webhook Notification**, and fill in the following information: | Field | Value | | :---------------------------------- | :------------------------------------------------- | | Notify me here when the alert fires | `https://app.chainpatrol.io/api/v2/canary/webhook` | It should look something like this when you are done: ![Canary Generation](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/canary.png) Click **Create Canarytoken**. After the token is created, you will see the modal with the token information. ![Canary Success](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/canary-success.png) Click **Manage Canarytoken** to navigate to the token's page. You should save this current page's URL for future reference. This is a uniquely generated URL containing the token that you can come back to see the history of the your Canary Token. Example: `https://canarytokens.org/nest/manage//` In order for ChainPatrol to automatically detect cloned websites, **send this URL to ChainPatrol via a secure channel**. We will connect your token to your organization's account. Finally, to complete the setup of the Canary Token, you need to add the generated JavaScript snippet to the domain that you indicated earlier. 1. Toggle ON the **"Obfuscate this script"** option and copy the generated code. 2. Paste the code into your website's HTML code, preferably in the `` tag on the homepage. > **Note:** We recommend turning OFF **Email Alerts**, since they may include localhost URLs and other false positives. We will handle the alerts via webhook. ## What happens when a cloned website is detected? When your website is cloned, we will create a new report in your ChainPatrol dashboard. ChainPatrol will proceed to block and takedown the malicious cloned site. ![Canary Report](https://mintlify.s3.us-west-1.amazonaws.com/chainpatrol/images/canary-report.png) # Submit Assets for Threat Detection Source: https://chainpatrol.io/docs/security-integration/submit-assets-for-scanning Submit a link to have it scanned and added to your organization's threat detection sources ## What is Asset Threat Detection? When submitting an Asset for threat detection, ChainPatrol will run our threat engine against all submitted assets to determine if they are malicious or impersonating your organization. If the asset passes an initial check, a report will be automatically created under your organization. ## Enabling External Threat Sources for your Organization Reach out to the ChainPatrol team to enable external threat sources for your organization. This will allow you to submit links to be scanned and added to your organization's threat detection sources through the API. ## API Key Required If you don't already have an API key, you can reach out to your ChainPatrol contact to get one. ## Submitting Assets for Threat Detection Make a call to the [Asset-Submit API](https://chainpatrol.io/docs/external-api/asset-submit) with a list of the links that you want checked. Your ChainPatrol contact will confirm that submissions are being processed.