Address
解析和构造 CKB 地址——地址中编码了 Lock 脚本和网络前缀。
CKB 地址是一个 bech32m 编码的字符串,其中打包了两部分信息:
- Lock 脚本——决定谁可以花费该地址下 Cell 的链上判定逻辑(
codeHash、hashType和args)。 - 网络前缀——主网用
ckb,测试网用ckt。
由于 Lock 脚本已内嵌于地址中,向某个地址发送资产时,可以直接从地址还原出所需的脚本,无需额外元数据。
Address 类
ccc.Address 将 Script 与网络前缀绑定在一起:
export class Address {
constructor(
public script: Script,
public prefix: string, // "ckb" | "ckt"
) {}
}凡接受 AddressLike 的 API,都可以传入已有的 Address 实例或普通对象——Address.from() 会做归一化处理:
const address = ccc.Address.from({
script: { codeHash: "0x...", hashType: "type", args: "0x..." },
prefix: "ckb",
});使用方法
解析地址字符串
Address.fromString 将地址字符串解码为结构化对象:
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 对象字典:
const address = await ccc.Address.fromString(someAddress, {
ckb: new ccc.ClientPublicMainnet(),
ckt: new ccc.ClientPublicTestnet(),
});从脚本构造地址
直接由 Lock 脚本和 client 构造 Address:
const address = ccc.Address.fromScript(lockScript, client);
console.log(address.toString()); // "ckb1q..."也可以从内置的 KnownScript 派生:
const address = await ccc.Address.fromKnownScript(
client,
ccc.KnownScript.Secp256k1Blake160,
"0xPublicKeyHash...",
);从 Signer 获取地址
在 dApp 中,最便捷的方式是直接从已连接的 Signer 获取地址:
// 推荐地址的字符串形式
const addressStr = await signer.getRecommendedAddress();
// 推荐地址的 Address 对象(包含 Lock 脚本)
const addressObj = await signer.getRecommendedAddressObj();
const { script: lock } = addressObj;
// 该 Signer 控制的所有地址
const allAddresses = await signer.getAddresses(); // string[]需要 Lock 脚本时(例如将其设为交易输出的接收方),优先使用 getRecommendedAddressObj,而不是先调用 getRecommendedAddress 再对结果执行 Address.fromString。
将地址转换为字符串
对任意 Address 实例调用 toString(),得到 bech32m 编码的地址字符串:
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 读取前缀:
const client = new ccc.ClientPublicTestnet();
console.log(client.addressPrefix); // "ckt"不要混用主网和测试网地址。将 ckt 地址传给主网 client 会抛出异常。使用 Address.fromString 时,务必配合正确网络的 client。
进阶:底层解析
绝大多数应用场景,Address.fromString 和 Address.fromScript 已经足够。如果需要在不发起 Client 请求的情况下检查或转换地址,可以使用 cccA 进阶命名空间中暴露的底层步骤:
import { cccA } from "@ckb-ccc/ccc/advanced";addressPayloadFromString
解码 bech32/bech32m 封装,返回原始的 format byte 和 payload——不解析任何 KnownScript:
const { prefix, format, payload } = cccA.addressPayloadFromString(
"ckb1qzda0cr08m85hc8jlnfp3sdrlalyatuqvqdveld...",
);
// prefix: "ckb"
// format: cccA.AddressFormat.Full
// payload: number[](codeHash + hashType + args 字节)优先尝试 bech32m 解码,失败后回退到旧版 bech32。两者均不匹配时,抛出 Unknown address format。
addressFromPayload
将解码后的 payload 还原为 AddressLike,并通过 client 解析 Short 格式的脚本索引:
const addressLike = await cccA.addressFromPayload(prefix, format, payload, client);
const address = ccc.Address.from(addressLike);Address.fromString 的实现正是 addressPayloadFromString + 前缀校验 + addressFromPayload 三步的组合。
最后更新于