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

# 钱包开发者集成指南

> 面向为 Monad 提供更好支持的钱包团队的指南和实用方案

文章面向在希望在 EVM 钱包中添加或改进 Monad 网络支持的钱包团队。Monad 与大多数 EVM 钱包兼容 — 使用与以太坊相同的地址、交易格式、签名和 dapp 连接流程。但有少量网络级差异 — 按 gas limit 计费、异步执行、 无全局 mempool 视图 — 会改变钱包应如何报价 gas、轮询状态和展示待处理状态。

对于终端用户,请参见[将 Monad 添加到钱包](/zh/guides/add-monad-to-wallet)。

对于链 ID、RPC URL、代币和协议合约地址,请参见 [网络信息](/zh/developer-essentials/network-information)、 [`token-list`](https://github.com/monad-crypto/token-list) 和 [`protocols`](https://github.com/monad-crypto/protocols)。

## 调优 gas 处理

在 Monad 上,用户支付交易的 **gas limit**费用,而不是它实际使用的 gas。这是相对于以太坊在钱包端 最大的差异:大的安全缓冲会显著过度收费用户,并预留交易永远不会使用的区块空间。

请使用小的、针对 Monad 的 gas limit 余量,并在用户手动将 gas limit 设置得远高于估计值时予以警告。

[Category Labs 的 gas limit 分析](https://www.category.xyz/blogs/setting-your-gas-limit-on-monad) 推荐使用 `eth_estimateGas` 加上适度的缓冲。固定缓冲是一个不错的起点;一旦有足够的历史数据进行校准, 可以将相同用户地址和调用函数的具体使用量作为动态缓冲量值缩减gas limit大小。

根据当前Monad的数据获取报价，而非以太坊的默认值

* `eth_maxPriorityFeePerGas` 返回硬编码的 2 gwei — 不是主网推荐值。
* 当 `newest_block` 为 `latest` 时,`eth_feeHistory` 会重复最新的 `baseFeePerGas`。不要在图表或平均值中重复计算。

参见 [Gas 定价](/zh/developer-essentials/gas-pricing) 和 JSON-RPC [费用估算说明](/zh/reference/json-rpc/overview#fee-estimation)。

## 处理交易生命周期

`eth_sendRawTransaction` 成功仅意味着"被此 RPC 节点接受" — 并不保证交易会落地或成功。 RPC 节点可能在检查 nonce 和余额与最新状态之前就接受它。

区分三个阶段:

| 阶段       | 显示内容   | 信号                                     |
| -------- | ------ | -------------------------------------- |
| 已提交      | 待处理    | `eth_sendRawTransaction` 返回哈希          |
| 被包含且本地执行 | 已完成或失败 | `eth_getTransactionReceipt` 返回 Receipt |
| 已最终确认    | 已最终确认  | Receipt 的区块编号小于或等于 `finalized` 标签返回的区块 |

如果一个账户刚收到 MON 并即将花费它,请等到接收交易的 Receipt 区块比当前区块至少落后 `k` 个区块。 目前 `k = 3`(约 1.2 秒),但这可能会改变。

如果一次花费使未委托账户的余额降至 10 MON 以下,请等待 `k` 个区块后再进行另一次 MON 花费。 取消委托后,请等待 `k` 个区块后再清空账户。

Monad 没有全局 mempool。不要使用 `txpool_content` 或 `newPendingTransactions` 来查看待处理状态。而是:

* 跟踪您提交的交易的本地待处理 nonce。
* 与 Receipt 和 `eth_getTransactionCount` 进行对账。
* 使用 `txpool_statusByAddress` 或 `txpool_statusByHash` 获取节点级待处理状态。
* 将待处理列表的范围限制为用户的账户,而不是整个网络。

## 模拟和 RPC 差异

`debug_trace*` 方法不返回 opcode 级 struct 日志。请使用 call frame 或 prestate tracer 进行模拟和风险预览。

WebSocket 订阅:`newHeads`、`logs`,以及针对预最终确认数据的 Monad 特定 `monadNewHeads` 和 `monadLogs`。 不支持 `syncing` 和 `newPendingTransactions` WebSocket 订阅类型。 参见 [WebSocket 订阅](/zh/reference/json-rpc/overview#websocket-subscriptions)。

全节点可能提供近期状态,但不提供任意旧状态。在显示历史状态 UI 或旧区块模拟之前请检查 RPC 能力, 并在需要时链接到归档端点。参见[历史数据](/zh/developer-essentials/historical-data)。

## EIP 和 EVM 差异

Monad 支持交易类型 0、1、2 和 4。不支持类型 3 的 blob 交易。

| 功能       | 状态              | 钱包影响                                                                                   |
| -------- | --------------- | -------------------------------------------------------------------------------------- |
| EIP-4844 | 不支持             | 拒绝类型 3 交易构造并给出清晰的错误。                                                                   |
| EIP-7702 | 支持,带 Monad 特定限制 | 已委托的 EOA 可以持有少于 10 MON,但任何会将其余额降至 10 MON 以下的交易都会回滚。已委托的账户代码也不能运行 `CREATE` 或 `CREATE2`。 |

Monad 的合约大小限制比以太坊大,并且有一些 opcode 重新定价。请使用 Monad 特定的 部署大小警告阈值,并按链重新估算,而不是硬编码 opcode 成本。参见[与以太坊的差异](/zh/developer-essentials/differences)。

## 实用方案

### 应用特定于链的 gas limit 余量

使用 Category Labs 的 7.5% 固定缓冲结果作为 Monad 起点,然后根据生产数据调优 — 成功率、重试次数和 gas 不足事件。基点可避免浮点舍入误差。

```ts theme={null}
const DEFAULT_GAS_LIMIT_MARGIN_BPS = 15_000n // 1.5x

const GAS_LIMIT_MARGIN_BPS_BY_CHAIN: Record<number, bigint> = {
  // 7.5% buffer. Measure against your wallet's transaction mix.
  143: 10_750n,
  10143: 10_750n,
}

export const applyGasLimitMargin = ({
  chainId,
  estimatedGas,
}: {
  chainId: number
  estimatedGas: bigint
}) => {
  const margin = GAS_LIMIT_MARGIN_BPS_BY_CHAIN[chainId] ?? DEFAULT_GAS_LIMIT_MARGIN_BPS
  return (estimatedGas * margin + 9_999n) / 10_000n
}
```

### 在手动 gas limit 超支时警告

```ts theme={null}
const CHAINS_CHARGING_GAS_LIMIT = new Set([143, 10143])
// Warn only on egregious overrides — not normal 1.5–2x safety buffers.
const OVERSPEND_WARNING_MULTIPLIER = 10n

export const shouldWarnGasLimitOverspend = ({
  chainId,
  gasLimit,
  recommendedGasLimit,
}: {
  chainId: number
  gasLimit: bigint
  recommendedGasLimit: bigint
}) => {
  if (!CHAINS_CHARGING_GAS_LIMIT.has(chainId)) return false
  if (recommendedGasLimit <= 0n || gasLimit < 21_000n) return false

  return gasLimit > recommendedGasLimit * OVERSPEND_WARNING_MULTIPLIER
}
```

请以内联方式显示此警告,并在签名前要求显式确认。当用户更改 gas limit 时重置该确认。

### 等待 Receipt 和最终性

下面的手动循环适用于标准 RPC。如果您的 RPC 支持,`eth_sendRawTransactionSync` 是更短的路径。

```ts theme={null}
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

const hexToBigInt = (hex: string) => BigInt(hex)

export const waitForReceipt = async (provider: EIP1193Provider, txHash: string) => {
  while (true) {
    // A Receipt means the transaction has executed locally on this RPC node.
    const receipt = await provider.request({
      method: "eth_getTransactionReceipt",
      params: [txHash],
    })

    if (receipt) return receipt
    await sleep(400)
  }
}

export const waitUntilFinalized = async (provider: EIP1193Provider, receiptBlockNumber: string) => {
  while (true) {
    // Compare the Receipt's block with the node's finalized commitment level.
    const finalizedBlock = await provider.request({
      method: "eth_getBlockByNumber",
      params: ["finalized", false],
    })

    if (hexToBigInt(finalizedBlock.number) >= hexToBigInt(receiptBlockNumber)) return
    await sleep(400)
  }
}
```

对普通状态使用 Receipt。在信贷桥接、存款或不可逆的链下结算之前等待最终性。

## 学习资源

<CardGroup cols={2}>
  <Card title="Gas 定价" href="/zh/developer-essentials/gas-pricing">
    Monad 如何收取 gas 以及 EIP-1559 如何在 Monad 上工作
  </Card>

  <Card title="JSON-RPC 概述" href="/zh/reference/json-rpc/overview">
    RPC 差异、区块标签、WebSocket、限制和错误
  </Card>

  <Card title="储备余额" href="/zh/developer-essentials/reserve-balance">
    账户何时可以低于 10 MON 储备花费
  </Card>

  <Card title="Monad 上的 EIP-7702" href="/zh/developer-essentials/eip-7702">
    已委托 EOA 的行为和 Monad 特定限制
  </Card>

  <Card title="历史数据" href="/zh/developer-essentials/historical-data">
    当前状态和历史状态的可用性
  </Card>
</CardGroup>
