

CKB 地址是一个 bech32m 编码的字符串，其中打包了两部分信息：

1. **Lock 脚本**——决定谁可以花费该地址下 Cell 的链上判定逻辑（`codeHash`、`hashType` 和 `args`）。
2. **网络前缀**——主网用 `ckb`，测试网用 `ckt`。

由于 Lock 脚本已内嵌于地址中，向某个地址发送资产时，可以直接从地址还原出所需的脚本，无需额外元数据。

## `Address` 类 [#address-类]

`ccc.Address` 将 `Script` 与网络前缀绑定在一起：

```ts
export class Address {
  constructor(
    public script: Script,
    public prefix: string, // "ckb" | "ckt"
  ) {}
}
```

凡接受 `AddressLike` 的 API，都可以传入已有的 `Address` 实例或普通对象——`Address.from()` 会做归一化处理：

```ts
const address = ccc.Address.from({
  script: { codeHash: "0x...", hashType: "type", args: "0x..." },
  prefix: "ckb",
});
```

## 使用方法 [#使用方法]

### 解析地址字符串 [#解析地址字符串]

`Address.fromString` 将地址字符串解码为结构化对象：

```ts
import { ccc } from "@ckb-ccc/ccc";

const client = new ccc.ClientPublicMainnet();
const address = await ccc.Address.fromString(
  "ckb1qzda0cr08m85hc8jlnfp3sdrlalyatuqvqdveld...",
  client,
);

console.log(address.script.codeHash); // Lock 脚本 code hash
console.log(address.script.hashType); // "type" | "data"
console.log(address.script.args);     // Lock 脚本 args
console.log(address.prefix);          // "ckb"
```

该方法会校验地址前缀与 `client` 所在网络是否匹配，不匹配时抛出异常（例如将 `ckt` 地址传给主网 `client`）。

如果同一段代码需要同时处理两个网络，可以传入一个 `client` 对象字典：

```ts
const address = await ccc.Address.fromString(someAddress, {
  ckb: new ccc.ClientPublicMainnet(),
  ckt: new ccc.ClientPublicTestnet(),
});
```

### 从脚本构造地址 [#从脚本构造地址]

直接由 Lock 脚本和 `client` 构造 `Address`：

```ts
const address = ccc.Address.fromScript(lockScript, client);
console.log(address.toString()); // "ckb1q..."
```

也可以从内置的 `KnownScript` 派生：

```ts
const address = await ccc.Address.fromKnownScript(
  client,
  ccc.KnownScript.Secp256k1Blake160,
  "0xPublicKeyHash...",
);
```

### 从 Signer 获取地址 [#从-signer-获取地址]

在 dApp 中，最便捷的方式是直接从已连接的 Signer 获取地址：

```ts
// 推荐地址的字符串形式
const addressStr = await signer.getRecommendedAddress();

// 推荐地址的 Address 对象（包含 Lock 脚本）
const addressObj = await signer.getRecommendedAddressObj();
const { script: lock } = addressObj;

// 该 Signer 控制的所有地址
const allAddresses = await signer.getAddresses(); // string[]
```

<Callout type="info">
  需要 Lock 脚本时（例如将其设为交易输出的接收方），优先使用 `getRecommendedAddressObj`，而不是先调用 `getRecommendedAddress` 再对结果执行 `Address.fromString`。
</Callout>

### 将地址转换为字符串 [#将地址转换为字符串]

对任意 `Address` 实例调用 `toString()`，得到 bech32m 编码的地址字符串：

```ts
const str = address.toString(); // "ckb1q..." | "ckt1q..."
```

`toString()` 始终生成当前推荐的长（Full）地址格式。CCC 为了向后兼容可以解析旧版（legacy）格式，但不会生成它们。

## 地址格式 [#地址格式]

CCC 支持四种地址格式，由首字节（format byte）区分。`toString()` 只输出 `Full` 格式，其余格式仅用于兼容 2021 年前的旧版地址。

| 格式         | 编码      | Payload 结构                                         | 备注                                      |
| ---------- | ------- | -------------------------------------------------- | --------------------------------------- |
| `Full`     | bech32m | `[0x00, codeHash(32), hashType(1), args]`          | 当前标准格式，由 `toString()` 输出。               |
| `FullData` | bech32  | `[0x02, codeHash(32), args]`，`hashType` 为 `"data"` | 2019 年旧版格式。                             |
| `FullType` | bech32  | `[0x04, codeHash(32), args]`，`hashType` 为 `"type"` | 2019 年旧版格式。                             |
| `Short`    | bech32  | `[0x01, scriptIndex(1), args(20)]`                 | 通过脚本索引（scriptIndex）而非完整 code hash 编码脚本。 |

`Short` 格式通过脚本索引而非完整 `codeHash` 来标识脚本，支持以下脚本：

| `scriptIndex` | 脚本                              |
| ------------- | ------------------------------- |
| `0`           | `KnownScript.Secp256k1Blake160` |
| `1`           | `KnownScript.Secp256k1Multisig` |
| `2`           | `KnownScript.AnyoneCanPay`      |

解析 `Short` 格式地址需要 `Client`，用于查找索引对应脚本当前的 `codeHash` 和 `cellDeps`。

## 网络前缀 [#网络前缀]

| 前缀    | 网络  |
| ----- | --- |
| `ckb` | 主网  |
| `ckt` | 测试网 |

运行时可从 `client` 读取前缀：

```ts
const client = new ccc.ClientPublicTestnet();
console.log(client.addressPrefix); // "ckt"
```

<Callout type="warning">
  不要混用主网和测试网地址。将 `ckt` 地址传给主网 `client` 会抛出异常。使用 `Address.fromString` 时，务必配合正确网络的 `client`。
</Callout>

## 进阶：底层解析 [#进阶底层解析]

绝大多数应用场景，`Address.fromString` 和 `Address.fromScript` 已经足够。如果需要在不发起 `Client` 请求的情况下检查或转换地址，可以使用 `cccA` 进阶命名空间中暴露的底层步骤：

```ts
import { cccA } from "@ckb-ccc/ccc/advanced";
```

### `addressPayloadFromString` [#addresspayloadfromstring]

解码 bech32/bech32m 封装，返回原始的 format byte 和 payload——不解析任何 `KnownScript`：

```ts
const { prefix, format, payload } = cccA.addressPayloadFromString(
  "ckb1qzda0cr08m85hc8jlnfp3sdrlalyatuqvqdveld...",
);
// prefix:  "ckb"
// format:  cccA.AddressFormat.Full
// payload: number[]（codeHash + hashType + args 字节）
```

优先尝试 bech32m 解码，失败后回退到旧版 bech32。两者均不匹配时，抛出 `Unknown address format`。

### `addressFromPayload` [#addressfrompayload]

将解码后的 payload 还原为 `AddressLike`，并通过 `client` 解析 Short 格式的脚本索引：

```ts
const addressLike = await cccA.addressFromPayload(prefix, format, payload, client);
const address = ccc.Address.from(addressLike);
```

`Address.fromString` 的实现正是 `addressPayloadFromString` + 前缀校验 + `addressFromPayload` 三步的组合。


---

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