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

# Transaction

> Build, complete, and send CKB transactions using the cell model.

CKB uses a **cell model** (an evolution of Bitcoin's UTXO model). Every piece of on-chain state lives in a **cell**. A cell has:

* **capacity** — the amount of CKB shannons it holds (1 CKB = 10⁸ shannons)
* **lock script** — who can spend it (authorization)
* **type script** (optional) — what rules it must follow (validation)
* **data** (optional) — arbitrary bytes

A transaction consumes existing cells as **inputs** and produces new cells as **outputs**. The `Transaction` class in CCC is a builder that lets you describe what you want, then fills in the missing pieces automatically.

## Create a transaction

Use `Transaction.from` to construct a transaction from a plain object. You only need to specify the outputs you want — inputs and fees come later:

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

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

`ccc.fixedPointFrom(100)` converts a human-readable CKB amount into shannons (`100n * 10n ** 8n`).

You can pass initial inputs, cell deps, or witnesses if you already know them:

```ts theme={null}
const tx = ccc.Transaction.from({
  cellDeps: [...],
  inputs: [...],
  outputs: [...],
  outputsData: [...],
  witnesses: [...],
});
```

## Add outputs

After construction, add more outputs with `addOutput`:

```ts theme={null}
// Capacity is calculated automatically from the lock script size
tx.addOutput({ lock: recipientLock }, "0x");

// Provide an explicit capacity
tx.addOutput({ capacity: ccc.fixedPointFrom(50), lock: recipientLock });
```

## Complete inputs

Once you know what outputs the transaction must produce, call `completeInputsByCapacity` to collect enough input cells from the signer's wallet to cover the output capacity:

```ts theme={null}
await tx.completeInputsByCapacity(signer);
```

This iterates the signer's live cells, adding them as inputs until the total input capacity meets or exceeds the total output capacity. It throws `ErrorTransactionInsufficientCapacity` if the wallet does not have enough CKB.

## Pay fees

After inputs are complete, call `completeFeeBy` to calculate the required fee, add a change output back to the signer's address, and collect additional inputs if needed:

```ts theme={null}
await tx.completeFeeBy(signer);
```

You can pass an explicit fee rate (shannons per 1000 bytes) to override the network estimate:

```ts theme={null}
await tx.completeFeeBy(signer, 1000n);
```

Fee calculation accounts for the full serialized transaction size, including witnesses. The change output automatically goes to the signer's recommended address.

## Add cell deps

Scripts referenced by a transaction's inputs or outputs must be listed as **cell deps** so the CKB VM can load them. Use `addCellDepsOfKnownScripts` to look them up by name:

```ts theme={null}
await tx.addCellDepsOfKnownScripts(
  client,
  ccc.KnownScript.Secp256k1Blake160,
  ccc.KnownScript.XUdt,
);
```

Signers that handle known lock scripts (JoyID, OmniLock, etc.) add the required cell deps automatically during `signTransaction` / `sendTransaction`, so you typically only need to add deps for type scripts you introduce yourself.

## Full transfer example

The following example is taken directly from the CCC examples package. It sends 100 CKB to the signer's own recommended address:

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

// The receiver is the signer itself — resolve the address string
const receiver = await signer.getRecommendedAddress();

// Parse the receiver's lock script from the address
const { script: lock } = await ccc.Address.fromString(receiver, signer.client);

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

// Fill inputs to cover output capacity
await tx.completeInputsByCapacity(signer);

// Add a change output and pay the network fee
await tx.completeFeeBy(signer);

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

<Steps>
  <Step title="Describe outputs">
    Call `ccc.Transaction.from` with the outputs you want to create.
  </Step>

  <Step title="Collect inputs">
    Call `tx.completeInputsByCapacity(signer)` to pull in enough cells from the wallet.
  </Step>

  <Step title="Pay fees">
    Call `tx.completeFeeBy(signer)` to calculate and collect the network fee, and route change back to the signer.
  </Step>

  <Step title="Send">
    Call `signer.sendTransaction(tx)` to sign and broadcast. It returns the transaction hash.
  </Step>
</Steps>

## Key method reference

| Method                                             | Description                                 |
| -------------------------------------------------- | ------------------------------------------- |
| `Transaction.from(txLike)`                         | Construct a transaction from a plain object |
| `tx.addOutput(outputLike, data?)`                  | Append an output cell                       |
| `tx.addInput(inputLike)`                           | Append an input cell manually               |
| `tx.addCellDeps(...deps)`                          | Add cell dependencies                       |
| `tx.addCellDepsOfKnownScripts(client, ...scripts)` | Add cell deps by `KnownScript` enum         |
| `tx.completeInputsByCapacity(signer)`              | Auto-collect inputs to cover outputs        |
| `tx.completeFeeBy(signer, feeRate?)`               | Auto-pay fees and produce change            |

<Warning>
  Always call `completeInputsByCapacity` before `completeFeeBy`. Fee calculation depends on the final transaction size, which is not known until inputs (and their witnesses) are present.
</Warning>
