# @ethereum-sourcify/clear-signing 中文文档

规范地址：https://npmcn.com/package/%40ethereum-sourcify/clear-signing/

版本：0\.3\.1
npm 元数据更新时间：2026-10-29T15:00:04.004Z
中文译文更新时间：2026-11-13T23:41:15.891Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40ethereum-sourcify/clear-signing
原文对照：https://npmcn.com/package/%40ethereum-sourcify/clear-signing/?lang=original
项目主页：https://github.com/sourcifyeth/clear-signing#readme
源码仓库：https://github.com/sourcifyeth/clear-signing

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：870 kB，19 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.0\.0
- 运行依赖：2 个
- 首次发布：2026-05-12T10:41:30.293Z
- 最新版本发布：2026-10-29T15:00:03.614Z
- 近 30 天下载量：8452（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：16（近 12 个月 16 个）

## 中文简介

用于人类可读交易预览的清晰签名库

## 安装

```sh
npm install @ethereum-sourcify/clear-signing
```

也可以使用：`pnpm add @ethereum-sourcify/clear-signing`、`yarn add @ethereum-sourcify/clear-signing`、`bun add @ethereum-sourcify/clear-signing`

## README

# @etereum-surcify/ clear- signing (中文(简体) )

引用类型脚本执行 [ERC-7730:结构化数据清晰签名格式](https://eips.ethereum.org/EIPS/eip-7730)。 。 。 .

这个库将原始交易 calldata和EIP-712打出的数据转换为人可读的显示模型,使钱包能够准确显示用户的签名内容.

设计可跳入钱包代码库 :

-   运行在现代浏览器上,Node.js (≥22),和回放原生(ESM + CJS).
-   两个运行时间依赖: [`@noble/hashes`](https://github.com/paulmillr/noble-hashes) 财务报告和审定财务报表 [`@noble/curves`](https://github.com/paulmillr/noble-curves)。 。 。 .
-   纯格式化:没有 RPC 客户端, 没有令牌/ 链/ ENS 获取; 外部数据通过 : [`ExternalDataProvider`](https://npmcn.com/package/%40ethereum-sourcify/clear-signing/#readme-externaldataprovider)。 。 。 .
-   没有内部缓存 : 调用者在获取描述和索引时控制 .

## 钱包整合指南

融入钱包? 见 [钱包整合指南](https://npmcn.com/package/%40ethereum-sourcify/clear-signing/GUIDE.md)。 。 。 .

## 安装

```bash
npm install @ethereum-sourcify/clear-signing
```

## 快速启动

建议的模式:在应用程序启动时获取登记索引,并传递给每个 `format()` 编号 : `formatTypedData()` 电话 库不会在内部缓存取来索引——没有索引,每个格式调用再fetches.

```typescript
import {
  format,
  fetchPrebuiltRegistryIndex,
} from "@ethereum-sourcify/clear-signing";

// At app startup — fetch once, keep in memory.
const index = await fetchPrebuiltRegistryIndex();
const baseOpts = {
  descriptorResolverOptions: { type: "github" as const, index },
  externalDataProvider: {
    resolveToken: async (chainId, address) => {
      // return token metadata from your wallet's token list
      // or call the ERC-20 methods on-chain
      return { name: "Tether USD", symbol: "USDT", decimals: 6 };
    },
  },
};

// Reuse on every format call — no re-fetching of the index.
const result = await format(
  {
    chainId: 1,
    to: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
    data:
      "0x095ea7b3" +
      "0000000000000000000000001234567890abcdef1234567890abcdef12345678" + // spender
      "00000000000000000000000000000000000000000000000000000000000f4240", // value
  },
  baseOpts,
);

console.log(result.intent); // "Approve"
console.log(result.fields); // [{ label: "Spender", value: "0x1234..." }, { label: "Amount", value: "1 USDT" }]
console.log(result.interpolatedIntent); // "Approve 1 USDT to 0x1234..."
```

如果你省略 `index` (或 `descriptorResolverOptions` 完全如此, `format()` 仍然有效——它只是收集每个电话的预设索引.

## API 参考

### `format(tx, opts?)`

将单个交易的调用数据格式化为 `DisplayModel`。通过链和合同地址确定一个ERC-7730描述符,解码调用数据,并制作字段。 跌回一个 `rawCalldataFallback` 当没有描述符匹配时.

```typescript
async function format(
  tx: Transaction,
  opts?: FormatOptions,
): Promise<DisplayModel>;
```

```typescript
interface Transaction {
  chainId: number;
  to: string;
  data: string; // calldata as hex string
  value?: bigint;
  from?: string;
}
```

### `formatTypedData(typedData, opts?)`

将 EIP-712 输入的数据电文格式化为 `DisplayModel`通过域链和核查合同,确定一个ERC-7730描述符,与主类型匹配 `encodeType`,并制作地块。 要求数 `chainId` 财务报告和审定财务报表 `verifyingContract` 在域内.

```typescript
async function formatTypedData(
  typedData: TypedData,
  opts?: FormatOptions,
): Promise<DisplayModel>;
```

```typescript
interface TypedData {
  account: string; // signer address
  types: Record<string, TypeMember[]>;
  primaryType: string;
  domain: TypedDataDomain;
  message: Record<string, unknown>;
}
```

### `formatEip5792Batch(batch, opts?)`

格式化为 [EIP-5792 信息技术](https://eips.ethereum.org/EIPS/eip-5792) 批次调用为a `BatchDisplayModel`中,每个调用都通过 `format()`。批量级别 `interpolatedIntent` 将所有个人意图与 " 和 " 合并,具体方式如下: [ERC-7730 (英语)](https://eips.ethereum.org/EIPS/eip-7730)。 。 。 .

```typescript
async function formatEip5792Batch(
  batch: Eip5792Batch,
  opts?: FormatOptions,
): Promise<BatchDisplayModel>;
```

```typescript
interface Eip5792Batch {
  from?: string;
  chainId: number;
  calls: Eip5792Call[];
}

interface Eip5792Call {
  to?: string;
  data?: string;
  value?: bigint;
}
```

### `FormatOptions`

```typescript
interface FormatOptions {
  /**
   * Wallets should provide an object with async methods to resolve
   * external data like ENS names, token metadata, and NFT collection
   * names. The provided functions may use RPC calls or fetch data
   * from internal sources. This allows the library to remain
   * agnostic about how this data is fetched. If absent, the library
   * will fall back to raw formats for the corresponding fields.
   */
  externalDataProvider?: ExternalDataProvider;

  /**
   * Controls where descriptors are fetched from, and optionally carries a
   * `trustedTokens` list (see below). Defaults to the GitHub registry when
   * omitted.
   */
  descriptorResolverOptions?: GitHubResolverOptions | CustomResolverOptions;
}
```

### `ExternalDataProvider`

图书馆将所有外部数据解析到钱包中 。 钱包可能使用 RPC 调用来解决数据 。 见 [`src/types.ts`](https://npmcn.com/package/%40ethereum-sourcify/clear-signing/src/types.ts) 用于完整返回类型定义(例如:. `TokenResult`, (中文(简体) ), `ChainInfoResult`(见a/c.5/49/70,附件).

```typescript
interface ExternalDataProvider {
  /**
   * Raw chain access for checks the library performs itself. Required when an AttestationOptions policy
   * is set: the ERC-8176 revocation check reads the EAS contract on Ethereum
   * mainnet.
   */
  chainClient?: ChainClient;

  /**
   * Resolution for addressName formats. The wallet should verify whether the
   * address matches any of the provided accepted types (e.g., "eoa", "contract", ...)
   * if able to. If none of the types match, set typeMatch to false so the library
   * can include a warning in the DisplayModel. When acceptedTypes is absent, the
   * descriptor has no type constraint and typeMatch: true can be returned safely.
   */
  resolveLocalName?: (
    address: string,
    acceptedTypes?: DescriptorAddressType[],
  ) => Promise<AddressNameResult | null>;
  /**
   * Resolution for addressName formats. The wallet should verify whether the
   * address matches any of the provided accepted types (e.g., "eoa", "contract", ...)
   * if able to. If none of the types match, set typeMatch to false so the library
   * can include a warning in the DisplayModel. When acceptedTypes is absent, the
   * descriptor has no type constraint and typeMatch: true can be returned safely.
   */
  resolveEnsName?: (
    address: string,
    acceptedTypes?: DescriptorAddressType[],
  ) => Promise<AddressNameResult | null>;

  /** Resolution for tokenAmount formats. */
  resolveToken?: (
    chainId: number,
    tokenAddress: string,
  ) => Promise<TokenResult | null>;

  /** Resolution for nftName formats. */
  resolveNftCollectionName?: (
    chainId: number,
    collectionAddress: string,
  ) => Promise<NftCollectionNameResult | null>;

  /** Resolution for date format with blockheight encoding. */
  resolveBlockTimestamp?: (
    chainId: number,
    blockHeight: bigint,
  ) => Promise<BlockTimestampResult | null>;

  /** Resolution for chainId and amount formats. */
  resolveChainInfo?: (chainId: number) => Promise<ChainInfoResult | null>;

  /**
   * Decryption for fields carrying an `encryption` annotation. Optional and
   * scheme-specific. Return `null` when the value cannot be decrypted — the
   * field then renders the descriptor's `fallbackLabel`. See DECRYPTION.md.
   */
  resolveDecryptedValue?: (
    chainId: number,
    encryptedValue: string,
    params: {
      scheme: DescriptorFieldEncryptionScheme;
      contractAddress?: string;
    },
  ) => Promise<DecryptedValueResult | null>;
}

interface ChainClient {
  /** Performs eth_call against `chainId` and returns the 0x-hex return data. */
  call: (
    chainId: number,
    request: { to: string; data: string },
  ) => Promise<string>;
}
```

### 描述来源

描述从 [明确签名的登记册](https://github.com/ethereum/clear-signing-erc7730-registry) 默认在 GitHub 上。 见 [快速启动](https://npmcn.com/package/%40ethereum-sourcify/clear-signing/#readme-quick-start) 用于推荐的预选模式.

#### GitHub 注册( 默认)

过 `githubSource` 改为 `fetchPrebuiltRegistryIndex` 和比对 `descriptorResolverOptions`数字 :

```typescript
const index = await fetchPrebuiltRegistryIndex(source);
const opts = {
  descriptorResolverOptions: {
    type: "github" as const,
    githubSource: {
      repo: "ethereum/clear-signing-erc7730-registry", // default
      ref: "master", // default
    },
    index,
  },
};
```

#### 从描述文件构建索引

如果预设的索引缺失,或者您正在使用一个没有公布的分叉,请自己走入登记册 `createGitHubRegistryIndex()`。它的速度要慢得多(每个描述文件一个抓取对预建索引的两个),所以保留它用于设置时间.

#### 文件系统解析器( 只有节点)

对于节点中捆绑的描述符或测试,从本地目录中构建自己的索引并加载描述符JSON文件. 文件系统解析器生活在一个仅节点的子路径导出中, 因此它不会被浏览器捆绑 :

```typescript
import { format } from "@ethereum-sourcify/clear-signing";
import { createFilesystemResolver } from "@ethereum-sourcify/clear-signing/filesystem";
import type { RegistryIndex } from "@ethereum-sourcify/clear-signing";

const index: RegistryIndex = {
  calldataIndex: {
    "eip155:1:0xdac17f958d2ee523a2206206994597c13d831ec7":
      "path/to/descriptor.json",
  },
  typedDataIndex: {},
};

const result = await format(tx, {
  descriptorResolverOptions: {
    type: "custom",
    resolver: createFilesystemResolver({
      index,
      descriptorDirectory: "./descriptors",
    }),
  },
});
```

#### 自定义解析器

`{ type: "custom", resolver }` 接受任何匹配对象 `DescriptorResolver` 形状,因此可以插入任意描述源(在映射图中,自定义的 HTTP 端点,.):

```typescript
import type { DescriptorResolver } from "@ethereum-sourcify/clear-signing";

const resolver: DescriptorResolver = {
  index,
  fetchDescriptor: async (path) => {
    /* return parsed descriptor for `path` */
  },
};

const result = await format(tx, {
  descriptorResolverOptions: { type: "custom", resolver },
});
```

### 证明(ERC-8176)

描述符控制用户在签名前所看到的. 钱包不能使用未经审查的描述符 . [ERC-8176 (中文(简体) )](https://github.com/ethereum/ERCs/pull/1576) 增加一个审查层:审计员用一个 [埃及](https://attest.org/) 脱链证明。 登记册将证明文件存放在描述器旁边,单位为 `registry/<project>/sigs/`登记册 [`auditors/`](https://github.com/ethereum/clear-signing-erc7730-registry/tree/master/auditors) 目录列出审计员和审计准则.

设定 `attestations` 启用此检查的政策。 只有在您所信任的审计员之一有有效证明时,图书馆才接受描述文件:

```typescript
const result = await format(tx, {
  descriptorResolverOptions: {
    type: "github",
    index,
    attestations: {
      // Auditor addresses your wallet trusts — see the registry's auditors/ directory.
      trustedAttesters: ["0x3846c3A30E62075Fa916216b35EF04B8F53931f6"],
    },
  },
  externalDataProvider: {
    // Required when `attestations` is set. The library uses this raw eth_call
    // access to read the revocation state from the EAS contract on Ethereum
    // mainnet. See GUIDE.md.
    chainClient: {
      call: async (chainId, { to, data }) => rpcEthCall(chainId, to, data),
    },
  },
});
```

图书馆对每份证明进行离线核查(schema、descriptor hash、过期、签名、UID)。 然后它读取撤销状态 通过 `externalDataProvider.chainClient`当没有可信证明有效时,结果包含 `NO_TRUSTED_ATTESTATION` 警告,对于调用数据 `rawCalldataFallback`。 。 。 .

**没有 `attestations` 政策,图书馆使用登记册描述符,无需任何审查检查。 只用这个模式进行测试.**

注释:

-   政策需要 `externalDataProvider.chainClient`,而自定义解析器必须执行 `DescriptorResolver.fetchAttestation`。否则,每门分辨率都会失败 `ATTESTATION_OPTIONS_INCOMPLETE`。 。 。 .
-   捆绑的可信任的脚本描述符( E)`trustedTokens`)没有入门.
-   只支持带有EAA签名的EAS出链证明(第2版).

### 信任的令牌列表

登记处不能为每个标志持有描述符。 仍然使ERC-20和ERC-721的平坦互动(`transfer`, (中文(简体) ), `approve`, (中文(简体) ), `transferFrom`, (中文(简体) ), `safeTransferFrom`, (中文(简体) ), `setApprovalForAll`),添加一个 `trustedTokens` 列表为 `descriptorResolverOptions`地图 `chainId → tokenAddress → standard` (处理小写或EIP-55复验)。 何时 **无登记描述符解析** 对于交易合同,图书馆在上面查找;如果列出,交易来自 **捆绑 ERC-20 / ERC-721 模板描述符** 而不是回到原始的呼叫数据。 登记说明总是优先.

```typescript
import type { TrustedTokens } from "@ethereum-sourcify/clear-signing";

const trustedTokens: TrustedTokens = {
  1: {
    "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": "erc20", // USDC
    "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d": "erc721", // BAYC
  },
};

const result = await format(tx, {
  descriptorResolverOptions: { type: "github", index, trustedTokens },
});
```

信任完全委托给钱包。 图书馆从来不决定哪些合同值得信赖.

### 显示模式

所有格式函数返回 a `DisplayModel`数字 :

```typescript
/**
 * The complete display model produced by the library.
 *
 * According to ERC-7730, wallets have two display options:
 *   1. Show `intent` as an explanation what the contract call does, and
 *      `fields` as a list of labeled values representing the calldata parameters.
 *   2. Show `interpolatedIntent` as a short string presentation of intent and fields,
 *      which already has formatted field values embedded in it — in this case
 *      `fields` can be omitted or shown as supplementary detail.
 *
 * When interpolation fails or is not defined, wallets should fall back to Option 1.
 */
interface DisplayModel {
  /**
   * The intent from the resolved descriptor, representing a short
   * description of the operation, e.g. "Approve token spending".
   * Two possible forms:
   *   - A simple human-readable string
   *   - A list of human-readable key-value pairs
   */
  intent?: string | Record<string, string>;

  /**
   * Ordered list of fields to show to the user,
   * formatted according to their field format specification.
   */
  fields?: (DisplayField | DisplayFieldGroup)[];

  /**
   * Full sentence with formatted field values interpolated in, e.g.
   * "Approve USDC spending up to 1,000 USDC for Uniswap V3".
   * Absent when the descriptor does not define an interpolatedIntent,
   * or when interpolation fails.
   */
  interpolatedIntent?: string;

  /**
   * Additional metadata directly from the resolved descriptor.
   * Wallets may choose to display these items to provide additional
   * context about the contract being interacted with.
   */
  metadata?: {
    owner?: string;
    contractName?: string;
    info?: { deploymentDate?: string; url?: string };
  };

  /**
   * Raw calldata fallback when no descriptor matched or the descriptor was faulty.
   * Only present for calldata formatting — not applicable to EIP-712 typed data.
   */
  rawCalldataFallback?: RawCalldataFallback;

  /**
   * Warnings providing additional context, e.g. why
   * interpolation failed.
   */
  warnings?: Warning[];
}
```

### 批量显示模式

`formatEip5792Batch` 返回 a `BatchDisplayModel`数字 :

```typescript
/**
 * The `callDisplays` array has the same order as the input `calls`.
 * The batch `interpolatedIntent` joins all individual intents with " and ".
 */
interface BatchDisplayModel {
  interpolatedIntent?: string;
  warnings?: Warning[];
  callDisplays: DisplayModel[];
}
```

见 `src/types.ts` 用于完整类型定义.

## 已知的局限性——EIP-712指数覆盖率

GitHub 索引只显示密钥 EIP-712 描述符 `context.eip712.deployments`通过下列方式绑定的说明 `context.eip712.domain` 或者说 `context.eip712.domainSeparator` 无法预索引.

## 发展

```bash
npm install        # Install dependencies
npm run build      # Compile to dist/
npm test           # Run tests
npm run test:watch # Watch mode
```

## 相关

-   [清除签名网站](https://clearsigning.org/)
-   [ERC-7730 规格](https://eips.ethereum.org/EIPS/eip-7730)
-   [Ethereum 清晰签名登记簿](https://github.com/ethereum/clear-signing-erc7730-registry)

## 许可证

麻省理工学院

## 常见问题

### @ethereum-sourcify/clear-signing 是什么？

用于人类可读交易预览的清晰签名库

### 如何安装 @ethereum-sourcify/clear-signing？

在项目目录运行 npm install @ethereum-sourcify/clear-signing，或使用 pnpm add / yarn add / bun add。

### @ethereum-sourcify/clear-signing 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @ethereum-sourcify/clear-signing 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @ethereum-sourcify/clear-signing 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @ethereum-sourcify/clear-signing 可以商用吗？

@ethereum-sourcify/clear-signing 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @ethereum-sourcify/clear-signing 的下载量有多少？

根据 npm 官方下载统计，@ethereum-sourcify/clear-signing 在 2026/10/14 – 2026/11/12 这 30 天内被下载 8,452 次，日均约 282 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @ethereum-sourcify/clear-signing 还在维护吗？

最新版本 0\.3\.1 发布于 2026/10/29（15 天前）；至今共发布 16 个版本，其中过去 12 个月发布了 16 个；首次发布于 2026/05/12。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

