> ## 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.

# Send CKB

> Compose and broadcast a CKB transfer transaction using the CCC transaction builder. Covers single transfers, transfer-all, and fee estimation.

CCC provides a declarative transaction builder. You describe the outputs you want, then call helper methods to automatically select inputs and calculate fees. The pattern is the same regardless of which wallet type the user has connected.

## Prerequisites

* A connected signer from [`useSigner()`](/guides/connect-wallet) or a manual `signer.connect()` call.
* The `@ckb-ccc/connector-react` (React) or `@ckb-ccc/ccc` (Node.js/scripts) package installed.

## Transfer a fixed amount

<Steps>
  <Step title="Get the signer">
    Retrieve the active signer. In a React app use the `useSigner()` hook; in a script use a signer instance directly.

    ```tsx theme={null}
    import { ccc } from "@ckb-ccc/connector-react";

    const signer = ccc.useSigner(); // returns undefined when not connected
    if (!signer) return;
    ```
  </Step>

  <Step title="Resolve the destination address">
    Convert a bech32 CKB address string to a `lock` script using `ccc.Address.fromString()`. Pass the signer's client so the method can look up the correct address format for the current network.

    ```typescript theme={null}
    const receiver = "ckt1qzda0cr08m85hc8jlnfp3sdrp5mec2azpfhsaz6ghptrs4m9k0mj...";
    const { script: lock } = await ccc.Address.fromString(receiver, signer.client);
    ```
  </Step>

  <Step title="Build the transaction">
    Create a transaction that declares the outputs you want. Specify the amount in Shannon (1 CKB = 10⁸ Shannon). Use `ccc.fixedPointFrom()` to convert from a human-readable CKB value.

    ```typescript theme={null}
    const tx = ccc.Transaction.from({
      outputs: [
        {
          capacity: ccc.fixedPointFrom(100), // 100 CKB
          lock,
        },
      ],
    });
    ```

    <Info>
      Capacity is the amount of on-chain storage (and CKB) locked in the cell. For a plain CKB transfer the minimum capacity is 61 CKB (the byte size of the cell's structure).
    </Info>
  </Step>

  <Step title="Fill inputs automatically">
    Call `tx.completeInputsByCapacity(signer)` to have CCC scan the signer's cells and add enough inputs to cover the requested output capacity.

    ```typescript theme={null}
    await tx.completeInputsByCapacity(signer);
    ```
  </Step>

  <Step title="Calculate and pay the fee">
    Call `tx.completeFeeBy(signer)` to calculate the network fee, add a change output back to the signer if needed, and finalize the transaction.

    ```typescript theme={null}
    await tx.completeFeeBy(signer);
    ```
  </Step>

  <Step title="Sign and broadcast">
    Send the transaction. `signer.sendTransaction()` signs the transaction and submits it to the network, returning the transaction hash.

    ```typescript theme={null}
    const txHash = await signer.sendTransaction(tx);
    console.log("Transaction hash:", txHash);
    ```
  </Step>
</Steps>

### Full example

```typescript transfer.ts theme={null}
import { ccc } from "@ckb-ccc/ccc";

async function transferCkb(signer: ccc.Signer, toAddress: string) {
  // Resolve the destination lock script
  const { script: lock } = await ccc.Address.fromString(toAddress, signer.client);

  // Declare outputs
  const tx = ccc.Transaction.from({
    outputs: [{ capacity: ccc.fixedPointFrom(100), lock }],
  });

  // Auto-select inputs and compute fee
  await tx.completeInputsByCapacity(signer);
  await tx.completeFeeBy(signer);

  // Sign and broadcast
  const txHash = await signer.sendTransaction(tx);
  console.log("Transaction hash:", txHash);
  return txHash;
}
```

## Transfer all CKB

Use `completeInputsAll()` to sweep all cells into a single output, then `completeFeeChangeToOutput()` to deduct the fee from that output instead of adding a separate change cell.

```typescript transfer-all.ts theme={null}
import { ccc } from "@ckb-ccc/ccc";

async function transferAllCkb(signer: ccc.Signer, toAddress: string) {
  const { script: lock } = await ccc.Address.fromString(toAddress, signer.client);

  // Output with no capacity set — will be filled by completeFeeChangeToOutput
  const tx = ccc.Transaction.from({
    outputs: [{ lock }],
  });

  // Collect every cell owned by the signer
  await tx.completeInputsAll(signer);

  // Deduct the fee from output[0] and assign the remaining balance to it
  await tx.completeFeeChangeToOutput(signer, 0);

  const txHash = await signer.sendTransaction(tx);
  console.log("Transaction hash:", txHash);
  return txHash;
}
```

<Warning>
  `completeInputsAll()` consumes every live cell the signer controls, including any cells holding UDT tokens or Spore NFTs. Use it only when you intend to sweep the entire wallet.
</Warning>

## In a React component

```tsx send-button.tsx theme={null}
"use client";

import { useState } from "react";
import { ccc } from "@ckb-ccc/connector-react";

export function SendButton() {
  const signer = ccc.useSigner();
  const [txHash, setTxHash] = useState<string | null>(null);

  async function send() {
    if (!signer) return;

    const toAddress = await signer.getRecommendedAddress(); // send to self for demo
    const { script: lock } = await ccc.Address.fromString(toAddress, signer.client);

    const tx = ccc.Transaction.from({
      outputs: [{ capacity: ccc.fixedPointFrom(100), lock }],
    });

    await tx.completeInputsByCapacity(signer);
    await tx.completeFeeBy(signer);

    const hash = await signer.sendTransaction(tx);
    setTxHash(hash);
  }

  return (
    <div>
      <button onClick={send} disabled={!signer}>
        Send 100 CKB to self
      </button>
      {txHash && <p>Sent: {txHash}</p>}
    </div>
  );
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="UDT Tokens" icon="coins" href="/guides/udt-tokens">
    Transfer CKB-native fungible tokens with the UDT package.
  </Card>

  <Card title="Sign Message" icon="pen" href="/guides/sign-message">
    Sign an arbitrary message with the connected wallet.
  </Card>
</CardGroup>
