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

# Signer

> A unified wallet abstraction for connecting, signing messages, and sending transactions.

A `Signer` represents a connected wallet. It hides the differences between wallet implementations — browser extensions, mobile apps, hardware devices — behind a single interface. You use a signer to get addresses, check balances, sign messages, and submit transactions.

## Signer types

CCC supports wallets from multiple ecosystems. The `SignerType` enum identifies which ecosystem a signer belongs to:

| Value              | Ecosystem                                   |
| ------------------ | ------------------------------------------- |
| `SignerType.CKB`   | Native CKB wallets (e.g. JoyID)             |
| `SignerType.EVM`   | Ethereum-compatible wallets (e.g. MetaMask) |
| `SignerType.BTC`   | Bitcoin wallets (e.g. UniSat, OKX)          |
| `SignerType.Nostr` | Nostr clients                               |
| `SignerType.Doge`  | Dogecoin wallets                            |

Each signer type produces a valid CKB address using a lock script that corresponds to its native signing algorithm (secp256k1, EVM personal sign, BTC ECDSA, etc.).

## Connect and disconnect

```ts theme={null}
// Connect the wallet — may trigger a browser popup
await signer.connect();

// Check connection status
const connected = await signer.isConnected(); // boolean

// Disconnect when done
await signer.disconnect();
```

<Note>
  `connect()` is async and may throw if the user rejects the connection request. Always `await` it before calling any other method.
</Note>

## Get addresses

A signer can control more than one address (e.g. a BTC wallet with multiple account derivation paths). `getRecommendedAddress` returns the primary one as a string:

```ts theme={null}
const address = await signer.getRecommendedAddress();
console.log(address); // "ckb1q..." or "ckt1q..."
```

Use `getAddresses` to retrieve all controlled addresses:

```ts theme={null}
const addresses = await signer.getAddresses(); // string[]
```

Use `getRecommendedAddressObj` when you need the underlying `Address` object (which carries the lock script):

```ts theme={null}
const { script: lock } = await signer.getRecommendedAddressObj();
```

## Check balance

`getBalance` returns the total CKB capacity across all controlled addresses, in shannons (1 CKB = 10⁸ shannons):

```ts theme={null}
const shannons = await signer.getBalance();
const ckb = Number(shannons) / 1e8;
console.log(`${ckb} CKB`);
```

## Sign messages

Sign an arbitrary message and receive a structured `Signature` object:

```ts theme={null}
const sig = await signer.signMessage("Hello CKB!");
// sig.signature — raw signature string
// sig.identity   — signer's identity (usually the address)
// sig.signType   — e.g. SignerSignType.CkbSecp256k1
```

Verify a signature without knowing which signer type was used:

```ts theme={null}
const valid = await signer.verifyMessage("Hello CKB!", sig);
console.log(valid); // true
```

You can also verify statically:

```ts theme={null}
const valid = await ccc.Signer.verifyMessage("Hello CKB!", sig);
```

## Sign and send transactions

Build a transaction, then hand it to the signer. `sendTransaction` signs and broadcasts in one step:

```ts theme={null}
const tx = ccc.Transaction.from({ outputs: [{ capacity: ccc.fixedPointFrom(100), lock }] });
await tx.completeInputsByCapacity(signer);
await tx.completeFeeBy(signer);

const txHash = await signer.sendTransaction(tx);
```

If you need the signed transaction object before broadcasting (e.g. to inspect witnesses), use `signTransaction`:

```ts theme={null}
const signedTx = await signer.signTransaction(tx);
const txHash = await signer.client.sendTransaction(signedTx);
```

## Find cells and transactions

A signer exposes the same search helpers as `Client`, but scoped to the signer's own addresses:

```ts theme={null}
// Iterate cells owned by this signer
for await (const cell of signer.findCells({})) {
  console.log(cell.cellOutput.capacity);
}

// Iterate transactions involving this signer
for await (const tx of signer.findTransactions({})) {
  console.log(tx.txHash);
}
```

## Access the underlying client

Every signer holds a reference to the `Client` it was created with:

```ts theme={null}
const client = signer.client;
const tip = await client.getTip();
```

## Network preferences

When the UI needs to enforce a particular network, pass a `NetworkPreference` array to `matchNetworkPreference`. The signer returns the preferred entry when a switch is needed, or `undefined` when already on a compatible network:

```ts theme={null}
const preference = signer.matchNetworkPreference(
  [{ addressPrefix: "ckb", signerType: ccc.SignerType.CKB, network: "mainnet" }],
  currentNetwork,
);
if (preference) {
  // prompt the user to switch to preference.network
}
```

<Tip>
  In a dApp, obtain a `Signer` instance from a CCC connector component (React, Vue, etc.) rather than constructing one directly. The connector handles wallet discovery and network negotiation for you.
</Tip>
