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

# 使用 Web3Actions 进行模块化监控

> 使用 Web3 Actions 和 Alerts 构建模块化监控系统，跟踪链上事件、处理 traces 并通过 webhook 传递通知。

本指南演示如何构建一个灵活的监控系统，可以跟踪任何链上事件、处理事务数据并通过 webhook 传递实时通知。通过将 Tenderly Alert 系统强大的触发条件与 Web3Actions 结合，您将创建一个模块化的监控基础设施，可适应任何区块链监控需求，从简单的事件跟踪到复杂的多合约交互。

<Note>
  本指南假定您已拥有 Tenderly 账户并对 Web3Actions 和区块链事件有基本了解。
</Note>

<Card title="使用 Web3Actions 进行模块化监控" href="" />

## 前提条件

在开始之前，请确保您具备：

* [Node.js](https://nodejs.org/)（当前支持的最新版本为 **v20**）
* 已安装 [Tenderly CLI](https://github.com/Tenderly/tenderly-cli)
* 用于接收数据的 webhook 端点
* 对 TypeScript 的基本理解

## 系统设置

<Steps>
  ### 创建 Alert

  * **Alert Type：** 我们将其设置为 **Successful Transaction**。您可以在 [此处](/monitoring/alerts/types#successful-transaction) 找到详细步骤

  <Frame caption="设置 Successful Transaction 告警">
    <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/successful-transaction-alert-setup.png?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=1cdcf8993e7e2c3103b75373ba50a5f3" alt="Setup Successful Transaction Alert" width="2754" height="1744" data-path="images/alerts/successful-transaction-alert-setup.png" />
  </Frame>

  * **Alert Target：** 作为目标，我们将使用 **Tag**，它可以让我们监控所有带有特定标签的合约和钱包。您可以在此查看如何为 [合约](/developer-explorer/contracts#adding-tags-to-contracts) 或 [钱包](/developer-explorer/wallets#adding-tags-to-wallets) 添加 **Tag**。

  <Frame caption="将 Tag 设置为 Alert Target">
    <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/alert-tag-as-target.png?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=fd6734ef878ea316cfa0878a83b7a928" alt="Setup Tag as an Alert Target" width="2740" height="1354" data-path="images/alerts/alert-tag-as-target.png" />
  </Frame>

  * **Alert Parameter：** 从下拉菜单中选择包含我们要监控合约的 **Tag**

  <Frame caption="选择您想使用的 Tag">
    <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/tag-as-alert-parameter.png?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=3f01512085b5a49b93b69e81a5315212" alt="Choose Tag you want to use" width="2742" height="1194" data-path="images/alerts/tag-as-alert-parameter.png" />
  </Frame>

  * **Alert Destination：** 目前您可以设置任何您想要的目标，在下一阶段我们将设置 Web3Action 作为此 Alert 的 Destination

  ### 安装依赖

  * 克隆仓库。您可以在 [此处](https://github.com/Tenderly/flexible-monitoring-solution) 找到模板链接

  * 克隆仓库后，在 CLI 中运行以下命令：

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  cd actions && npm install
  ```

  ### 配置环境变量

  在您的 Tenderly Web3Action 中设置以下 [Secrets](/monitoring/web3-actions/references/context#secrets)：

  ```env showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  WEBHOOK_URL = <Your webhook URL>
  BEARER = <Your Tenderly API bearer token>
  ACCOUNT_SLUG = <Your Tenderly account slug>
  PROJECT_SLUG = <Your project slug>
  EVENT_NAME = <Name of the event to track>
  ```

  ### 配置 tenderly.yaml

  您的 `tenderly.yaml` 应该如下所示：

  ```yaml showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  account_id: "<YOUR_ACCOUNT_ID>"
  actions:
    <YOUR_ACCOUNT_ID>/<PROJECT_SLUG>:
      runtime: v2
      sources: actions
      specs:
        example:
          description: "Event tracking system"
          function: example:modularFn
          trigger:
            type: alert
            alert: { <YOUR_ALERT_ID> }
          execution_type: parallel
  project_slug: "<PROJECT_SLUG>"
  ```

  请确保将占位符替换为以下值：

  * `YOUR_ACCOUNT_ID`：您的账户 ID，可按照 [本指南](/platform/account/projects/slug) 获取。
  * `PROJECT_SLUG`：您的项目 slug，可按照 [本指南](/platform/account/projects/slug) 获取。
  * `YOUR_ALERT_ID`：您在上一步中创建的告警 ID。您可以在 dashboard 中找到该 ID。

  <Frame caption="查找 Alert ID">
    <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/alert-id.png?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=b637e922e730f0e99a5c3c45ea9de811" alt="Finding the Alert ID" width="2942" height="2090" data-path="images/alerts/alert-id.png" />
  </Frame>

  ### 部署您的 Web3 Action

  运行以下命令来部署您的 Web3 Action：

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  tenderly actions deploy
  ```
</Steps>

## 核心组件

### 事务处理

系统从处理事务信息开始：

```typescript showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
export const modularFn = async (context: Context, transactionEvent: TransactionEvent) => {
  const txHash = transactionEvent.hash;
  const txNetwork = transactionEvent.network;

  const blockHash = transactionEvent.blockHash;
  const blockNumber = transactionEvent.blockNumber;

  const WEBHOOK_URL = await context.secrets.get("WEBHOOK_URL");
  const BEARER = await context.secrets.get("BEARER");
  const ACCOUNT_SLUG = await context.secrets.get("ACCOUNT_SLUG");
  const PROJECT_SLUG = await context.secrets.get("PROJECT_SLUG");
  const EVENT_NAME = await context.secrets.get("EVENT_NAME");

  if (!EVENT_NAME) {
    throw new Error("EVENT_NAME not found in environment variables");
  }

  const url = `https://api.tenderly.co/api/v1/public-contract/${txNetwork}/trace/${txHash}`;

  const traceResponse = await axios.get(url, {
    headers: {
      authorization: BEARER,
    },
  });

  const traceData = traceResponse.data;
```

此组件：

* 捕获事务哈希和网络
* 通过 Tenderly API 获取事务 traces
* 处理区块信息

### 合约信息检索

使用 [Contracts API](/api-reference) 获取合约信息（名称和 ABI）。

```typescript showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
const fetchContractName = async (addr: string) => {
  const contractEndpoint = `https://api.tenderly.co/api/v1/account/${ACCOUNT_SLUG}/project/${PROJECT_SLUG}/contract/${txNetwork}/${addr}`;

  try {
    const contractResponse = await axios.get(contractEndpoint, {headers: {'Authorization': BEARER}});
    return contractResponse.data.contract.contract_name;
  } catch (error) {
    console.error(`Error fetching contract name from endpoint for ${addr}:`, error);
  }
};

const fetchContractAbi = async (addr: string) => {
  const contractEndpoint = `https://api.tenderly.co/api/v1/account/${ACCOUNT_SLUG}/project/${PROJECT_SLUG}/contract/${txNetwork}/${addr}`;

  try {
    const contractResponse = await axios.get(contractEndpoint, {headers: {'Authorization': BEARER}});
    return contractResponse.data.contract.data.abi;
  } catch (error) {
    console.error(`Error fetching contract ABI from endpoint for ${addr}:`, error);
  }
};
```

### 事件处理

事件处理通过专门的函数进行：

```typescript showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
const extractEventAddresses = (logs: any[]): string[] =>
  Array.from(new Set(
    logs
      .filter(log => log.name === EVENT_NAME)
      .map(log => log.raw.address)
  ));

const extractEventDetails = (logs: any[]) => {
  return logs
    .filter(log => log.name === EVENT_NAME)
    .map(log => {
      const result: { [key: string]: string } = {
        name: log.name
      };

    log.inputs.forEach((input: any) => {
      const name = input.soltype.name;
      const value = input.value.toString();
      result[name] = value;
    });

    return result;
  });
};
```

此部分：

* 按名称过滤事件
* 提取事件参数
* 处理事件地址

## Webhook 交互

系统使用 Axios 将这些结构化数据发送到您的 webhook：

```typescript showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{
  hash: string,              // Transaction hash
  transaction: object,       // Full transaction event
  blockHash: string,        // Block hash
  blockNumber: number,      // Block number
  matchReasons: Array<{     // Event details
    name: string,
    [parameterName: string]: string
  }>,
  sentinel: {               // Contract information
    contractName: string,
    abi: object
  },
  traceData: object,        // Transaction trace data
  addresses: string[]       // Involved addresses
}
```

## 故障排除

常见问题及解决方案：

1. **缺失事件**
   * 验证 EVENT\_NAME 与合约事件完全匹配
   * 检查 Tenderly dashboard 中的告警配置
   * 查看事务日志以确认事件是否被发出

2. **API 错误**
   * 验证 BEARER token 权限
   * 检查 API 端点可用性
   * 验证网络配置

3. **Webhook 问题**
   * 确认 WEBHOOK\_URL 可访问
   * 检查负载格式是否符合预期
   * 监控 webhook 端点日志
