# The Fuel TypeScript SDK (`fuels`) — Admin & Architecture Guide

This guide is for the engineers, architects, and contributors who need to understand how `fuels-ts` is **built** — its monorepo layout, package dependency graph, the Sway→TypeScript codegen pipeline, the UTXO transaction-assembly engine, the ABI coder, binary management, and the release machinery. For day-to-day SDK usage, see the companion **User Guide**.

`fuels-ts` is the official TypeScript SDK for the [Fuel](https://fuel.network/) network. It is a **pnpm + Turborepo monorepo** that publishes ~20 scoped `@fuel-ts/*` packages, an umbrella `fuels` package (which re-exports them all and carries the CLI), a `create-fuels` scaffolding tool, and an `@fuel-ts/abi-typegen` code generator. It is licensed **Apache-2.0**.

---

## 1. Executive Summary

| Attribute | Value |
|---|---|
| Project | `fuels-ts` — Fuel TypeScript SDK |
| Author | Fuel Labs |
| License | Apache-2.0 |
| Language | TypeScript |
| Repository | `git+https://github.com/FuelLabs/fuels-ts.git` |
| Monorepo manager | pnpm `^9.4.0` workspaces |
| Build orchestrator | Turborepo (`turbo`) |
| Per-package bundler | `tsup` (esbuild) → CJS + ESM + IIFE |
| Test runner | Vitest (node + browser projects) + Playwright |
| Release tooling | Changesets |
| Node support | `^20.0.0 \|\| ^22.0.0 \|\| ^24.0.0` |
| External binaries | `forc` (Sway compiler), `fuel-core` (node) |

**What it is.** A client SDK that lets TypeScript applications create wallets, deploy and call Sway programs (contracts, scripts, predicates), and build/submit transactions on a UTXO-based chain. Conceptually it is to Fuel what `ethers.js` is to Ethereum, plus a build tool that bridges the Sway compiler to typed TypeScript bindings.

**Audience inversion note.** Although automated classification tags the repo as a web app, it is a **library/framework/CLI**. Throughout this guide the "operator" is a developer integrating or extending the SDK, and "deployment" means publishing packages and managing the toolchain — not running a server.

---

## 2. Architecture

### 2.1 High-level layers

```
            ┌─────────────────────────────────────────────────────────┐
            │                     fuels (umbrella)                     │
            │   re-exports every @fuel-ts/* package + the `fuels` CLI  │
            └───────────────┬─────────────────────────┬───────────────┘
                            │                         │
        ┌───────────────────▼──────────┐   ┌──────────▼───────────────┐
        │      High-level objects      │   │         CLI layer        │
        │  account · contract ·        │   │  init/build/deploy/dev/  │
        │  program · script · recipes  │   │  node/typegen/versions   │
        └───────────────┬──────────────┘   └──────────┬───────────────┘
                        │                              │
        ┌───────────────▼──────────────┐   ┌──────────▼───────────────┐
        │     Encoding & protocol      │   │     Codegen + binaries   │
        │  abi-coder · transactions ·  │   │  abi-typegen ·           │
        │  address · math · hasher     │   │  @internal/forc ·        │
        │  crypto · utils · errors     │   │  @internal/fuel-core     │
        └──────────────────────────────┘   └──────────────────────────┘
```

The dependency direction is strictly downward: high-level objects (`Contract`, `Wallet`) build on the encoding/protocol layer (`abi-coder`, `transactions`), which builds on primitives (`math`, `crypto`, `errors`). The CLI sits beside the runtime and pulls in `abi-typegen` plus the binary-management packages.

### 2.2 Package inventory

**Published runtime packages (`@fuel-ts/*`)**

| Package | Responsibility |
|---|---|
| `account` | The largest package. `Account`, `Wallet` (locked/unlocked), `HDWallet`, `Mnemonic`, `Signer`, `WalletManager` (+ vaults/storages), `Predicate`, the `Provider`, transaction requests/responses/summaries, connectors (`Fuel`, `FuelConnector`), assets, and coin-consolidation utilities |
| `contract` | `ContractFactory` (deploy), contract loader scripts, contract ID/root helpers |
| `program` | The invocation-scope engine (`FunctionInvocationScope`, multicall, `Script`-request base) shared by contracts/scripts |
| `script` | The `Script` high-level class |
| `abi-coder` | Binary encode/decode of every Sway type — the `Interface` class and the `Coder` family (`StructCoder`, `EnumCoder`, `VecCoder`, `OptionCoder`, `B256Coder`, `BigNumberCoder`, …) |
| `abi-typegen` | Code generator: ABI JSON → typed TS classes; ships the `fuels-typegen` CLI |
| `transactions` | Transaction & receipt coders (the wire format) |
| `address` | `Address` parsing/conversion (`b256`, bech32-style, EVM addresses) |
| `crypto` | `encrypt`/`decrypt`, `keccak256`, `scrypt`, `pbkdf2`, `randomBytes`, with separate `node` and `browser` implementations behind one API |
| `hasher` | Hashing helpers (sha256, address hashing) |
| `math` | The `BN` big-number type and `bn()` factory |
| `merkle` | Binary / sparse / sum Merkle tree implementations |
| `utils` | Shared helpers, bytecode (de)compression, test-utils, default consensus key |
| `errors` | `FuelError` + the `ErrorCode` enum (the single error taxonomy) |
| `versions` | Version compatibility checking + the `versions` CLI |
| `recipes` | Pre-built reusable contracts (e.g. the SRC-14 owned proxy) |
| `logger` | A `debug`-based logger with Fuel-aware formatters |

**Aggregator & tooling packages**

| Package | Role |
|---|---|
| `fuels` | Umbrella: re-exports all of the above + `FuelAsm` (`@fuels/vm-asm`) + the CLI |
| `create-fuels` | `npm create fuels` scaffolder |
| `@internal/forc` | Downloads/installs the `forc` binary per platform |
| `@internal/fuel-core` | Downloads/installs the `fuel-core` binary per platform |
| `@internal/tsup` | Shared `tsup` bundler configurations |
| `@internal/check-imports`, `check-tests` | CI integrity checks |

The umbrella's public surface is defined entirely by `packages/fuels/src/index.ts`, which re-exports every sub-package. This barrel is the authoritative list of what `import { … } from 'fuels'` exposes.

### 2.3 Source tree

```
fuels-ts/
├── packages/          # ~20 published packages, each: src/ (barrel index.ts) + test/
│   ├── fuels/         #   umbrella + CLI (src/cli.ts, src/cli/commands/*)
│   ├── account/       #   Provider, Wallet, Predicate, tx requests (largest)
│   ├── abi-coder/     #   Interface + Coder family
│   ├── abi-typegen/   #   ABI → TS codegen + fuels-typegen CLI
│   ├── contract/ program/ script/ transactions/ address/ math/ …
│   └── create-fuels/  #   scaffolding CLI + templates
├── apps/
│   ├── docs/          # VitePress docs site; src/guide/**/snippets/*.ts are tested
│   ├── docs-api/      # generated API reference
│   └── demo-*/        # runnable example apps (nextjs, react-vite, bun, nodejs-esm)
├── templates/         # create-fuels templates (vite, nextjs)
├── internal/          # @internal/forc, @internal/fuel-core, tsup, check-*
└── scripts/           # release, changeset, forc-version, coverage tooling
```

> [!NOTE]
> Most of the 2,000+ files are Sway test fixtures under `packages/*/test/fixtures/forc-projects/**` and docs snippets. The actual SDK surface is the `packages/*/src/` trees, and the cleanest map to it is each package's `src/index.ts` barrel.

---

## 3. System Requirements

| Concern | Requirement |
|---|---|
| Node.js | `^20`, `^22`, or `^24` |
| Package manager (consumers) | npm / pnpm / yarn / bun |
| Package manager (contributors) | pnpm `^9.4.0` (declared `packageManager`) |
| Sway compiler | `forc` — version pinned per SDK release |
| Node binary | `fuel-core` — version pinned per SDK release |
| Browser | Modern evergreen browsers (a dedicated browser build ships) |

The `forc`/`fuel-core` versions are not free-floating: `create-fuels` writes a `fuel-toolchain` file pinning `forc` and `fuel-core` to the versions exported by `@fuel-ts/versions`, on the `testnet` channel. The `fuels versions` command exists precisely to catch drift between the installed binaries and the SDK's expected versions.

---

## 4. Configuration Mastery — `fuels.config.ts`

The `fuels` CLI is driven by a single config file resolved (via JoyCon) as `fuels.config.{ts,js,cjs,mjs}` walking up from the working directory. It is bundled and evaluated at runtime (`bundle-require` + esbuild), so it can be authored in TypeScript. Define it with `createConfig` for type-safety. Validation is enforced by a `yup` schema (`output` is the only strictly required field).

### 4.1 Full field reference

| Field | Type | Default | Notes |
|---|---|---|---|
| `output` | `string` | — | **Required.** Directory for generated TypeScript. Resolved against the config's dir. |
| `workspace` | `string` | — | Path to a Forc workspace. Mutually exclusive with `contracts`/`scripts`/`predicates`. |
| `contracts` | `string[]` | `[]` | Individual contract program paths. |
| `scripts` | `string[]` | `[]` | Individual script program paths. |
| `predicates` | `string[]` | `[]` | Individual predicate program paths. |
| `autoStartFuelCore` | `boolean` | `true` | Auto-start a local `fuel-core` during `dev`/`node`. |
| `fuelCorePort` | `number` | `4000` | Port for the auto-started node. |
| `providerUrl` | `string` | `process.env.FUEL_NETWORK_URL` ?? `http://127.0.0.1:4000/v1/graphql` | Network the CLI deploys to. |
| `privateKey` | `string` | `defaultConsensusKey` | Deployer key. Override via the `MY_PRIVATE_KEY` env var in real deployments. |
| `forcPath` | `string` | resolved on `PATH` | Path to the `forc` binary. |
| `fuelCorePath` | `string` | resolved on `PATH` | Path to the `fuel-core` binary. |
| `forcBuildFlags` | `string[]` | `[]` | Extra flags to `forc build`. Presence of `--release` selects `buildMode: 'release'`, else `'debug'`. |
| `deployConfig` | `object \| fn` | `{}` | Per-deploy options (storage slots, configurables). |
| `snapshotDir` | `string` | — | Chain-config snapshot directory; watched by `dev`/`node`. |
| `onBuild` / `onDeploy` / `onDev` / `onNode` / `onFailure` | callbacks | — | Lifecycle hooks invoked by the CLI. |

Two derived fields are computed at load time and merged into the in-memory config: `basePath` (the config dir), `configPath` (the resolved file), and `buildMode` (`'release'` if `--release` is in `forcBuildFlags`, else `'debug'`). The `buildMode` selects the artifact directory the CLI reads from: `out/{buildMode}/{name}.bin`, `…-abi.json`, and `…-storage_slots.json`.

> [!IMPORTANT]
> `output` must be a valid string or `validateConfig` rejects the file. `workspace` must point at a directory whose `Forc.toml` declares `[workspace]`; pointing it at a single program throws `WORKSPACE_NOT_DETECTED` and suggests using `contracts`/`scripts`/`predicates` instead.

### 4.2 Environment variables

The CLI and examples read a handful of env vars:

| Variable | Used for |
|---|---|
| `FUEL_NETWORK_URL` | Default `providerUrl` when not set in config |
| `MY_PRIVATE_KEY` | Deployer key in `fuels.config.ts` |
| `FUEL_CORE_PATH` | Locating the `fuel-core` binary in test setup |

> [!CAUTION]
> The default `privateKey` is the well-known local consensus key — convenient for `fuels dev` against a local node, **never** for testnet/mainnet. Always inject a real key via `MY_PRIVATE_KEY` (or another secret source) for non-local deployments.

---

## 5. The Sway → TypeScript Codegen Pipeline

This is the SDK's signature subsystem: turning compiled Sway programs into typed TypeScript.

### 5.1 The build/deploy flow (`fuels build`, `fuels deploy`)

```
forc build (Sway compiler)
   └─ out/{debug|release}/{name}.bin
      out/{debug|release}/{name}-abi.json
      out/{debug|release}/{name}-storage_slots.json
        │
        ▼
abi-typegen  →  typed TS classes  (Contract/Factory, Script[+Loader], Predicate[+Loader])
        │
        ▼
fuels deploy → deploys, writes contract-ids.json, regenerates factory classes with loader code
```

`forcUtils.ts` is the glue: it reads each program's `Forc.toml` to discover the project name, the Sway program type (`contract`/`script`/`predicate`/`library`), and computes the `.bin`/`-abi.json`/`-storage_slots.json` paths from `buildMode`. `findPrograms()` globs for `*.toml`, filters out the workspace root and libraries, and classifies the rest by reading the `;`-terminated program-type line in each `src/main.sw`.

`deploy()` (in `cli/commands/deploy`) runs in order: deploy contracts → save `contract-ids.json` → deploy scripts → save script files → deploy predicates → save predicate files → fire the `onDeploy` callback → regenerate factory classes so they embed loader bytecode.

### 5.2 `abi-typegen` internals

The generator (`AbiTypeGen`) consumes the new ABI JSON shape (`JsonAbiNew`; an older shape is transpiled forward via `transpileAbi`). For each program it builds an `Abi` model exposing `types`, `functions`, `configurables`, `commonTypesInUse`, and bytecode, then renders Handlebars (`.hbs`) templates:

- **Contract** → `renderMainTemplate` emits the typed contract class with per-function encoders/decoders, struct/enum typedefs, the embedded ABI JSON, and storage slots. Base members imported: `FunctionFragment`, `InvokeFunction`.
- **Predicate** → requires a `main()` function (else `ABI_MAIN_METHOD_MISSING`); imports `Predicate`, `Provider`, `InputValue`, `PredicateParams`, `decompressBytecode`; embeds compressed bytecode.
- **Script** → also requires `main()`; imports `Script`, `Account`, `decompressBytecode`.
- **index** → `renderIndexTemplate` re-exports the generated members.

Struct/enum/import formatting is handled by `formatStructs`/`formatEnums`/`formatImports`. The CLI surface (`fuels-typegen`) is a commander program with `-i/--inputs`, `-o/--output`, mutually-exclusive `-c/-s/-p`, and `-S/--silent`; `resolveProgramType` defaults to `CONTRACT` when none is specified.

> [!NOTE]
> Predicates and scripts can be deployed as reusable **loader bytecode**. After `fuels deploy`, the generator re-emits `*Loader` classes that reference the on-chain blob, keeping per-transaction payloads small. This is why deploy regenerates types as its final step.

---

## 6. The Transaction-Assembly Engine (UTXO)

Fuel is UTXO-based, so the hardest problems in the SDK are **coin selection** and **fee estimation**. This logic lives in `@fuel-ts/account` under `providers/`.

### 6.1 Transaction request types

`providers/transaction-request/` defines a request hierarchy, each a coder over the wire format:

| Request | Used for |
|---|---|
| `ScriptTransactionRequest` | Script execution and transfers (the workhorse) |
| `CreateTransactionRequest` | Contract creation/deployment |
| `BlobTransactionRequest` | Uploading bytecode blobs (loader pattern) |
| `UpgradeTransactionRequest` / `UploadTransactionRequest` | Chain/state upgrades |

Requests expose `addCoinOutput`, `addContractInputAndOutput`, `addResources`, `addWitness`/`updateWitness`, `setData`, and `getTransactionId(chainId)`.

### 6.2 `assembleTx` — the modern funding API

`provider.assembleTx({ request, feePayerAccount, accountCoinQuantities })` is the recommended way to fund and estimate any hand-built request. The caller declares which account supplies which `{ amount, assetId }` and where change goes (`changeOutputAccount`); the engine selects coins, estimates gas/fee, and returns a ready-to-send `assembledRequest`. Because assembly can mutate the request (adding inputs/outputs and changing the tx ID), signatures must be (re)applied **after** assembly — see the signing flow in the User Guide.

### 6.3 Coin management utilities

`@fuel-ts/account` exports UTXO-shaping helpers:

| Export | Purpose |
|---|---|
| `consolidateCoins` / `consolidateCoinsIfRequired` | Merge many small coins into few (avoids the input-count limit) |
| `getAllCoins` | Fetch every coin for an asset across pages |
| `assembleTransferToContractScript` | Build the script data for contract transfers |
| `Account.batchTransfer` | Many transfers in one transaction |
| `Account.generateFakeResources` | Synthesize resources for dry-runs |

The `Provider` carries an optional resource cache (`resourceCacheTTL`) to prevent the same coin from being selected by two in-flight transactions (double-spend protection at the client level). `Provider.ENABLE_RPC_CONSISTENCY` toggles a cross-node consistency check.

### 6.4 Transaction lifecycle

```
build request → assembleTx (select coins, estimate fee)
   → sign (if required) → sendTransaction / .call()
   → TransactionResponse → waitForResult()
   → TransactionSummary (status, receipts, fee, decoded logs)
```

`transaction-summary/` assembles human-readable summaries from raw receipts, including operation classification and fee calculation. `transaction-response/getDecodedLogs` and `getAllDecodedLogs` turn receipts into typed log values (and the grouped-by-contract logs the User Guide demonstrates).

---

## 7. The ABI Coder

`@fuel-ts/abi-coder` is the binary serialization layer. The `Interface` class wraps an ABI and exposes `functions.<name>.encodeArguments(...)` / `decodeOutput(...)`. Encoding is delegated to a family of `Coder` subclasses, one per Sway type:

`ArrayCoder`, `B256Coder`, `B512Coder`, `BigNumberCoder`, `BooleanCoder`, `ByteCoder`, `EnumCoder`, `NumberCoder`, `OptionCoder`, `RawSliceCoder`, `StdStringCoder`, `StrSliceCoder`, `StringCoder`, `StructCoder`, `TupleCoder`, `VecCoder`.

It also exports the protocol size constants (`WORD_SIZE`, `BYTES_32`, `ASSET_ID_LEN`, `CONTRACT_ID_LEN`, `INPUT_COIN_FIXED_SIZE`, `SCRIPT_FIXED_SIZE`, `calculateVmTxMemory`) and the encoding version flag `ENCODING_V1`. The new ABI type (`JsonAbi`, from `types/JsonAbiNew`) is the canonical shape; legacy ABIs are transpiled.

> [!NOTE]
> The coder family is the lowest-level public contract in the SDK. If you ever need to encode/decode against a raw ABI without a generated class, construct an `Interface` directly — this is what the generated classes do under the hood.

---

## 8. Binary Management — `forc` & `fuel-core`

The SDK does not bundle the Rust binaries; the `@internal/forc` and `@internal/fuel-core` packages download the correct binary per platform/architecture at install time (`lib/install.js`, `lib/shared.js`). They detect the architecture and throw `Unsupported arch ${process.arch}` for unsupported platforms, and validate the version string.

At runtime the CLI's `tryFindBinaries` resolves `forcPath`/`fuelCorePath` either from config or the system `PATH`; if a binary is missing it throws with a message listing each missing binary and a link to the installation guide. `autoStartFuelCore` (in the `dev`/`node` commands) spawns a `fuel-core` child process on `fuelCorePort` and tears it down on config change or shutdown.

> [!TIP]
> For consumers, the recommended install path is `fuelup`, which manages matched `forc`/`fuel-core` toolchains by channel. The `@internal/*` download packages exist mainly so the monorepo's own tests and the scaffolded templates get a known-good binary without a manual `fuelup` step.

---

## 9. Security

| Surface | Handling |
|---|---|
| **Private keys** | Never logged. `WalletUnlocked` holds the key in memory; `WalletLocked` holds only an address. `lock()` drops the key. |
| **Keystores** | `Wallet.encrypt`/`fromEncryptedJson` use scrypt-derived AES (the `crypto` package), with separate hardened node/browser implementations. |
| **`WalletManager`** | Vaults stay encrypted until `unlock(password)`; `lock()` clears secrets. `updatePassphrase` rotates without re-importing keys. |
| **Default consensus key** | Used only as the local-dev deployer default; documented as unsafe for real networks (override via `MY_PRIVATE_KEY`). |
| **Double-spend protection** | Provider `resourceCacheTTL` prevents reusing a coin across concurrent in-flight transactions. |
| **Predicates** | Spend authorization is enforced on-chain by the predicate program, not by client trust. |
| **Network transport** | `requestMiddleware` allows injecting auth/credentials; `timeout` and `retryOptions` bound exposure to a hung or flaky node. |
| **Configurable validation** | Configurable constants are type-checked against the ABI before deploy, rejecting malformed structs. |

> [!CAUTION]
> Treat `fuels.config.ts` as code: it is bundled and **executed** by the CLI. Do not commit real `privateKey` values into it — read them from the environment.

---

## 10. Operations — the CLI dev loop

The `fuels` CLI (`packages/fuels/src/cli.ts`) is a commander program named `fuels` with global `-D/--debug` and `-S/--silent` flags (wired through a `preAction` hook into `configureLogging`). Commands:

| Command | Action module | Behavior |
|---|---|---|
| `init` | `commands/init` | Discovers programs, writes `fuels.config.ts` (errors if it exists) |
| `build` | `commands/build` | `forc build` + typegen; `--deploy` also deploys |
| `deploy` | `commands/deploy` | Deploys contracts→scripts→predicates, saves IDs, regenerates types |
| `dev` | `commands/dev` | `autoStartFuelCore` → build+deploy → watch config/Sway/snapshot with `chokidar`, rebuild on change |
| `node` | `commands/node` | Start `fuel-core` from config and watch for config changes |
| `typegen` | delegates to `@fuel-ts/abi-typegen/cli` | ABI → TS |
| `versions` | delegates to `@fuel-ts/versions/cli` | Compatibility check |

The `dev`/`node` commands wrap their actions in `withConfig`/`withProgram`/`withBinaryPaths` higher-order handlers that load + validate config and resolve binaries before running, and route failures through `withConfigErrorHandler` (which can invoke the `onFailure` hook).

### 10.1 Local development workflow

```bash
pnpm install          # install workspace
pnpm build:packages   # turbo build all publishable packages (excludes docs/templates)
pnpm test:node        # vitest node project
pnpm test:browser     # vitest browser project (Playwright-backed)
pnpm lint             # type-check + eslint + prettier
```

The root `package.json` exposes the full operational surface: `turbo run build` for the dependency-aware build graph; `vitest` split into `node` and `browser` projects with separate configs; coverage merge/diff scripts; `forc:check`/`forc:verify`/`forc:update` to keep the Sway toolchain pinned; and `changeset:*` scripts for release.

---

## 11. Testing Strategy

| Layer | Tooling |
|---|---|
| Unit & integration | Vitest, split into `node` and `browser` projects (`vitest.node.config.mts`, `vitest.browser.config.mts`) |
| Browser execution | `@vitest/browser` over Playwright |
| Coverage | Istanbul, with `test:coverage-merge` / `test:coverage-diff` to combine node+browser and gate PRs |
| Test selection | `scripts/tests-find.sh` filters by `--node/--browser/--e2e/--integration/--network` |
| End-to-end | Real network tests gated on `NETWORK_TEST_URL` + `NETWORK_TEST_PVT_KEY` env vars |
| Docs snippets | Every `apps/docs/src/guide/**/snippets/*.ts` is a compiled, executed test (tagged `@group node`/`@group browser`) |
| Ephemeral node | `launchTestNode()` (in `@fuel-ts/account`/`utils` test-utils) spins up `fuel-core` with funded wallets, auto-torn-down via `using` |
| Forc fixtures | `turbo run test:forc` compiles the Sway fixture projects under each package's `test/fixtures/forc-projects/**` |

The docs-as-tests approach is notable: the user-facing examples cannot drift from the API, because they are typechecked and run in CI. `expectToThrowFuelError` (from `@fuel-ts/errors/test-utils`) asserts a specific `FuelError` code is thrown.

---

## 12. Error Code Reference

All SDK errors are `FuelError` instances with a stable string `code` from the `ErrorCode` enum (`packages/errors/src/error-codes.ts`). `FuelError` also carries `metadata`, `rawError`, and `VERSIONS` (the SDK/binary versions at throw time), and `FuelError.parse()` rehydrates a serialized error (rejecting unknown codes). Selected codes by domain:

| Domain | Representative codes |
|---|---|
| ABI / codegen | `no-abis-found`, `abi-main-method-missing`, `configurable-not-found`, `type-not-supported`, `invalid-decode-value`, `unsupported-encoding-version`, `bin-file-not-found` |
| Config / CLI | `config-file-not-found`, `config-file-already-exists`, `workspace-not-detected` |
| Address | `invalid-address`, `invalid-evm-address`, `invalid-b256-address` |
| Provider | `chain-info-cache-empty`, `missing-provider`, `connection-refused`, `invalid-url`, `response-body-empty` |
| Wallet / account | `invalid-public-key`, `wallet-manager-error`, `hd-wallet-error`, `account-required`, `unlocked-wallet-required`, `invalid-password` |
| Funds / coins | `not-enough-funds-or-max-coins-reached`, `not-enough-funds`, `max-coins-reached`, `unable-to-consolidate-coins`, `no-coins-to-consolidate`, `coins-asset-id-mismatch` |
| Transaction | `gas-limit-too-low`, `max-fee-too-low`, `gas-price-too-low`, `transaction-failed`, `transaction-squeezed-out`, `invalid-configurable-constants`, `max-inputs-exceeded`, `max-outputs-exceeded`, `asset-burn-detected`, `change-output-collision`, `contract-size-exceeds-limit` |
| Mnemonic | `invalid-mnemonic`, `invalid-entropy`, `invalid-seed`, `invalid-checksum`, `invalid-word-list` |
| Script | `script-reverted`, `script-return-invalid-type` |
| Node / misc | `node-launch-failed`, `rpc-consistency`, `not-implemented`, `unknown` |

> [!TIP]
> Branch on `error.code`, never the message — messages are human-facing and may change; codes are part of the contract. The full enum is the canonical, exhaustive list.

---

## 13. Known Issues, Tech Debt & Roadmap

Drawn from the project's own issue tracker at analysis time:

| Issue | Area | Notes |
|---|---|---|
| #3803 (open) | UTXO | *"No Coins Available or exceeding 255 Coin Limit"* — the coin-input ceiling; mitigated by `consolidateCoins`, tracked for a smoother flow (#3808 auto-consolidation). |
| #3935 (open) | Logs | Allow filtering logs by type. |
| #3593 (open) | Configurables | Support dynamic configurables. |
| #3941 (open) | Typegen | Generated relative imports omit the `.js` extension (ESM resolution). |
| #3930 (open) | Assets | Deprecate `assets`. |
| #3724 (open) | Tooling | Migrate `eslint` + `prettier` to `biome`. |
| #2477 (open) | Architecture | Consider merging `hasher` into `crypto`. |
| #2478 (open) | Architecture | Consider merging `script` into `program`. |

These reflect the SDK's direction: smoother UTXO management (auto-consolidation), richer log handling, ESM-correct codegen, and package consolidation (`hasher`→`crypto`, `script`→`program`) to shrink the dependency graph.

---

## 14. Release & Distribution

| Step | Mechanism |
|---|---|
| Versioning | Changesets (`@changesets/cli`); `changeset:next`, `changeset:version-with-docs` |
| Build | `turbo run build` (dependency-aware) → each package bundled by `tsup` to CJS/ESM/IIFE with sourcemaps and `keepNames` |
| Publish | `changeset:publish` over the workspace; packages are versioned in lock-step |
| Deprecation | `release-deprecate.ts` |
| Toolchain sync | `forc:update`/`forc:verify`/`verify-forc-version` keep the pinned Sway compiler current |
| Dependency hygiene | `knip` (unused deps), `syncpack` (version alignment across the workspace) |

Because every `@fuel-ts/*` package is published in lock-step and the umbrella `fuels` re-exports them, a consumer almost always depends on a single `fuels` version and gets a consistent set of sub-packages.

---

## 15. Quick Reference

### Package dependency direction

```
fuels  →  account · contract · program · script · recipes   (high-level)
           │
           ▼
        abi-coder · transactions · address                   (encoding/protocol)
           │
           ▼
        math · crypto · hasher · merkle · utils · errors      (primitives)

CLI(fuels)  →  abi-typegen · @internal/forc · @internal/fuel-core
```

### Key files for contributors

| Want to change… | Read |
|---|---|
| Public SDK surface | `packages/fuels/src/index.ts` (barrel) |
| CLI commands | `packages/fuels/src/cli.ts` + `cli/commands/*` |
| Config loading/validation | `packages/fuels/src/cli/config/{loadConfig,validateConfig,forcUtils}.ts` |
| Codegen | `packages/abi-typegen/src/**` (templates in `templates/*/main.ts` + `.hbs`) |
| Coin selection / funding | `packages/account/src/providers/**` (`assembleTx`, transaction-request) |
| Binary encode/decode | `packages/abi-coder/src/**` |
| Error taxonomy | `packages/errors/src/error-codes.ts` |

### Operational commands

```bash
pnpm install && pnpm build:packages   # bootstrap + build
pnpm test:node                         # run node tests
pnpm lint                              # type + eslint + prettier
pnpm changeset                         # record a release note
npx fuels versions                     # check forc/fuel-core compatibility
```

---

_Generated June 2026 from FuelLabs/fuels-ts at b3f37c9. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
