> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ckbccc.com/llms.txt - append ".md" to any page URL for its Markdown source.
> Use this file to discover all available pages before exploring further.

---
# Address
URL: https://docs.ckbccc.com/en/docs/concepts/address
Source: https://raw.githubusercontent.com/ckb-devrel/ccc/refs/heads/dev/packages/docs/content/docs/concepts/address.mdx
> Parse and construct CKB addresses, which encode a lock script and network prefix.


A CKB address is a bech32m-encoded string that packages two things:

1. **A lock script** — the on-chain predicate that controls who can spend cells at this address (`codeHash`, `hashType`, and `args`).
2. **A network prefix** — `ckb` for mainnet, `ckt` for testnet.

Because the lock script is embedded in the address, you can always recover the exact script needed to send funds — no additional metadata required.

## The `Address` class [#the-address-class]

`ccc.Address` pairs a `Script` with a network prefix:

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

Wherever an API accepts an `AddressLike`, you can pass an existing `Address` or a plain object — `Address.from()` normalizes both:

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

## Usage [#usage]

### Parse an address string [#parse-an-address-string]

`Address.fromString` parses an encoded CKB address into a structured object. If
the string is not an encoded address, the client's optional `addressResolver`
can resolve another representation, such as a name:

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

const clientOwner = ccc.ClientPublicMainnet.open();
const client = clientOwner.value;
// Call `await clientOwner.dispose()` when it is no longer needed.
const address = await ccc.Address.fromString(
  "ckb1qzda0cr08m85hc8jlnfp3sdrlalyatuqvqdveld...",
  client,
);

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

For encoded addresses, it validates that the prefix matches the client's
network and throws on a mismatch (e.g. passing a `ckt` address to a mainnet
client).

Passing a prefix-keyed record of clients is deprecated. When you need to handle
both networks in the same code path, try the clients explicitly and handle the
failed attempt at the call site:

```ts
const clientsOwner = ccc.OwnerAggregated.from([
  ccc.ClientPublicMainnet.open(),
  ccc.ClientPublicTestnet.open(),
] as const);
const [mainnetClient, testnetClient] = clientsOwner.value;
let address: ccc.Address;

try {
  try {
    address = await ccc.Address.fromString(someAddress, mainnetClient);
  } catch {
    address = await ccc.Address.fromString(someAddress, testnetClient);
  }
} finally {
  await clientsOwner.dispose();
}
```

### Resolve names and other representations [#resolve-names-and-other-representations]

Configure an `AddressResolver` when an application accepts representations
other than encoded CKB addresses:

```ts
const names: Record<string, ccc.ScriptLike> = {
  "alice.example": aliceLock,
};

const addressResolver: ccc.AddressResolver = {
  shouldResolve: (value) => value.endsWith(".example"),
  resolve: async (value) => names[value],
};

const clientOwner = ccc.ClientPublicMainnet.open({ addressResolver });
const address = await ccc.Address.fromString(
  "alice.example",
  clientOwner.value,
);
await clientOwner.dispose();
```

The resolver is consulted only after normal address parsing fails.
`shouldResolve` selects the representations it owns. If it returns `false`,
`Address.fromString` preserves the original parsing error; if `resolve` returns
`undefined`, it throws `Address ... not found`. A resolved script is paired with
the supplied client's network prefix.

### Construct an address from a script [#construct-an-address-from-a-script]

Build an `Address` directly from a lock script and a client:

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

Or derive one from a built-in `KnownScript`:

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

### Get an address from a signer [#get-an-address-from-a-signer]

In a dApp, the easiest way to get an address is directly from the connected signer:

```ts
// Primary address as a string
const addressStr = await signer.getRecommendedAddress();

// Primary address as an Address object (includes the lock script)
const addressObj = await signer.getRecommendedAddressObj();
const { script: lock } = addressObj;

// All addresses controlled by this signer
const allAddresses = await signer.getAddresses(); // string[]
```

<Callout type="info">
  Prefer `getRecommendedAddressObj` when you need the lock script — for example, to set it as a transaction output recipient — rather than calling `Address.fromString` on the string result.
</Callout>

### Convert an address to a string [#convert-an-address-to-a-string]

Call `toString()` on any `Address` instance to produce the bech32m string:

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

`toString()` always emits the modern **Full** format. CCC can parse legacy formats for backwards compatibility, but never emits them.

## Address formats [#address-formats]

CCC recognizes four on-the-wire formats, distinguished by their leading format byte. Only `Full` is produced by `toString()`; the rest exist for compatibility with pre-2021 addresses.

| Format     | Encoding | Payload layout                                        | Notes                                      |
| ---------- | -------- | ----------------------------------------------------- | ------------------------------------------ |
| `Full`     | bech32m  | `[0x00, codeHash(32), hashType(1), args]`             | Current standard. Emitted by `toString()`. |
| `FullData` | bech32   | `[0x02, codeHash(32), args]` — `hashType` is `"data"` | Legacy 2019 format.                        |
| `FullType` | bech32   | `[0x04, codeHash(32), args]` — `hashType` is `"type"` | Legacy 2019 format.                        |
| `Short`    | bech32   | `[0x01, scriptIndex(1), args(20)]`                    | Legacy short form for well-known scripts.  |

The `Short` format encodes a script by index rather than a full code hash. Supported scripts:

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

Decoding a short address requires a `Client` to look up the current `codeHash` and `cellDeps` for the indexed script.

## Network prefix [#network-prefix]

| Prefix | Network |
| ------ | ------- |
| `ckb`  | Mainnet |
| `ckt`  | Testnet |

Read the prefix at runtime from the client:

```ts
const clientOwner = ccc.ClientPublicTestnet.open();
const client = clientOwner.value;
// Call `await clientOwner.dispose()` when it is no longer needed.
console.log(client.addressPrefix); // "ckt"
```

<Callout type="warning">
  Never mix mainnet and testnet addresses. Passing a `ckt` address to a mainnet client will throw. Always pair `Address.fromString` with the correct client.
</Callout>

## Advanced: low-level parsing [#advanced-low-level-parsing]

For most apps, `Address.fromString` and `Address.fromScript` are all you need. When you need to inspect or transform an address without a `Client` round-trip, CCC exposes the underlying steps via the `cccA` advanced namespace:

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

### `addressPayloadFromString` [#addresspayloadfromstring]

Decodes the bech32/bech32m envelope and returns the raw format byte and payload — without resolving any `KnownScript`:

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

Tries bech32m first, falls back to legacy bech32. Throws `Unknown address format` if neither matches.

### `addressFromPayload` [#addressfrompayload]

Turns a decoded payload back into an `AddressLike`, resolving short-format script-index lookups against the client:

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

For an encoded address, `Address.fromString` combines
`addressPayloadFromString` + prefix validation + `addressFromPayload`. If the
first step fails, it may instead delegate to the client's `addressResolver`.
