> For the complete documentation index, see [llms.txt](https://docs.bloxchain.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bloxchain.app/protocol/getting-started.md).

# Getting started

This guide shows the **simplest way** to start using the Bloxchain protocol: by connecting to an **Account‑based contract** that already combines all core components (`SecureOwnable`, `RuntimeRBAC`, `GuardController`) behind a single address.

For a deeper explanation of the pattern itself, see the [Account Pattern doc](/protocol/account-pattern.md).

## 📋 **Prerequisites**

* Node.js 18+
* TypeScript 4.5+
* npm or yarn
* Basic knowledge of Ethereum and smart contracts

Pin **`@bloxchain/sdk`** and optionally **`@bloxchain/contracts`** to exact versions in production. See [Versioning & releases](https://github.com/PracticalParticle/Bloxchain-Protocol/blob/99beac2d6e6d7567c23b25cecaf6f4053f31c987/docs/VERSIONING.md) for how npm semver relates to on-chain `EngineBlox.VERSION`.

## 🚀 **Installation**

```bash
npm install @bloxchain/sdk

# Or with yarn
yarn add @bloxchain/sdk
```

## 🔧 **Basic Setup (Account-Based Contract)**

### 1. **Import Required Dependencies**

```typescript
import {
  SecureOwnable,
  RuntimeRBAC,
  GuardController,
} from '@bloxchain/sdk';
import { createPublicClient, createWalletClient, http } from 'viem';
import { sepolia } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
```

### 2. **Initialize Clients**

```typescript
const rpcUrl = process.env.RPC_URL!;           // e.g. https://sepolia.infura.io/v3/...
const privateKey = process.env.PRIVATE_KEY!;   // never hardcode; use env vars

const account = privateKeyToAccount(privateKey);

// Public client for reads
const publicClient = createPublicClient({
  chain: sepolia,
  transport: http(rpcUrl),
});

// Wallet client for writes
const walletClient = createWalletClient({
  account,
  chain: sepolia,
  transport: http(rpcUrl),
});
```

### 3. **Connect to an Account-Based Contract**

Use a deployed Account implementation (for example `AccountBlox`) from `deployed-addresses.json`:

```typescript
// Example shape – adjust the import path to your deployed-addresses.json (often at the repository root)
import deployed from '../deployed-addresses.json';

const network = 'sepolia' as const;
const accountAddress = deployed[network].AccountBlox.address as `0x${string}`;

// All three wrappers point to the SAME address
const secureOwnable = new SecureOwnable(publicClient, walletClient, accountAddress, sepolia);
const runtimeRBAC = new RuntimeRBAC(publicClient, walletClient, accountAddress, sepolia);
const guardController = new GuardController(publicClient, walletClient, accountAddress, sepolia);
```

### Definition library addresses (public testnets)

Integrators need deployed **definition libraries** for execution-param helpers (`updateRecoveryExecutionParams`, batch encoders, schema refresh). Keys in `deployed-addresses.json` map to env vars:

| `deployed-addresses.json` key | Env variable                                                            |
| ----------------------------- | ----------------------------------------------------------------------- |
| `SecureOwnableDefinitions`    | `SECURE_OWNABLE_DEFINITIONS_ADDRESS`                                    |
| `RuntimeRBACDefinitions`      | `RUNTIME_RBAC_DEFINITIONS_ADDRESS`                                      |
| `GuardControllerDefinitions`  | `GUARD_CONTROLLER_DEFINITIONS_ADDRESS`                                  |
| `GuardControllerDefinitions`  | `DEFINITION_CONTRACT_ADDRESS` (alias for single schema-refresh address) |

Example for Sepolia:

```typescript
import deployed from '../deployed-addresses.json';

const network = 'sepolia' as const;
const sod = deployed[network].SecureOwnableDefinitions.address;
const rbd = deployed[network].RuntimeRBACDefinitions.address;
const gcd = deployed[network].GuardControllerDefinitions.address;
```

Pass these addresses to SDK helpers such as `updateRecoveryExecutionParams(client, sod, newRecovery)`.

***

## 📖 **Common Tasks with an Account**

### 1. **Inspect Ownership & Security State**

```typescript
// SecureOwnable – core security state
const owner = await secureOwnable.owner();
const broadcasters = await secureOwnable.getBroadcasters();
const recovery = await secureOwnable.getRecovery();
const timeLockPeriod = await secureOwnable.getTimeLockPeriodSec();

console.log({ owner, broadcasters, recovery, timeLockPeriod });

// RuntimeRBAC – roles and permissions
const supportedRoles = await runtimeRBAC.getSupportedRoles();
const firstRole = supportedRoles[0];
const roleInfo = await runtimeRBAC.getRole(firstRole);

console.log('First role info:', roleInfo);
```

### 2. **Perform a Secure Ownership Transfer**

```typescript
// 1) Owner (or recovery) requests a transfer (new owner is encoded in the state machine)
const txRequest = await secureOwnable.transferOwnershipRequest({
  from: account.address,
});

await publicClient.waitForTransactionReceipt({ hash: txRequest.hash });

// 2) After the timelock expires, approve the pending transaction (txId from BaseStateMachine.getPendingTransactions / getTransaction)
const baseStateMachine = new BaseStateMachine(publicClient, walletClient, accountAddress, sepolia);
const pendingTxIds = await baseStateMachine.getPendingTransactions();
const txId = pendingTxIds[0];

const txApprove = await secureOwnable.transferOwnershipDelayedApproval(txId, {
  from: account.address,
});

await publicClient.waitForTransactionReceipt({ hash: txApprove.hash });
```

### 3. **Guarded Call via GuardController**

Use the GuardController wrapper to execute a time‑locked call to a whitelisted target:

```typescript
import { EngineBlox } from '@bloxchain/sdk/lib/EngineBlox';

// Assume target is a whitelisted contract for a registered function selector
const target = '0x...'; // e.g. ERC20 token
const functionSelector = '0xa9059cbb' as `0x${string}`; // transfer(address,uint256)
const params = '0x...' as `0x${string}`; // abi-encoded params

const gasLimit = 300_000n;
const operationType = EngineBlox.NATIVE_TRANSFER_OPERATION; // or custom op type

const txResult = await guardController.executeWithTimeLock(
  target,
  0n,                    // value
  functionSelector,
  params,
  gasLimit,
  operationType,
  { from: account.address },
);

console.log('Requested guarded execution tx hash:', txResult.hash);
```

(Approvals, cancellations, and meta‑tx flows use the same patterns as described in the component‑specific docs.)

***

## Deployment and initialization

Account‑style contracts use OpenZeppelin **Initializable** semantics: there is **no constructor state** on the implementation; a single correct **`initialize(...)`** (or your product’s chained initializer) must run on the **proxy** (or minimal proxy). Treat **initialization as part of deployment**: the address end users call should not appear as a **public, uninitialized** proxy across block boundaries—wire **`initialize` in the same transaction** that creates the proxy (factory, proxy constructor `_data`, or equivalent), then rely on ownership, RBAC, and guards.

### **1. Recommended: factory / cloner pattern**

To avoid “forgot to call `initialize`” or wrong ordering when spinning up many instances, prefer a **factory** that creates the proxy and calls `initialize` **in the same transaction**. The repo includes **`CopyBlox`** as a reference pattern (`contracts/examples/applications/CopyBlox/CopyBlox.sol`):

* Validates the implementation implements **`IBaseStateMachine`**.
* **`Clones.clone`** (EIP‑1167) then **`call`s** `initialize(address,address,address,uint256,address)` on the new clone.
* If initialization **reverts**, the whole transaction **reverts**—you do not end up with a live, uninitialized clone from that path.

Use the same **initializer arity and argument order** your concrete contract exposes (often the same five parameters as `CopyBlox` / `BaseStateMachine`).

### **2. Proxy deploy runbook (atomic `initialize`)**

If you deploy transparent / UUPS / ERC‑1967–style proxies yourself, you still must avoid a **live, public proxy that is uninitialized** between transactions. Prefer **one atomic transaction** that both **creates** the proxy and **runs `initialize`**—for example:

* OpenZeppelin **proxy constructors** that accept **`_data`**: supply ABI‑encoded **`initialize(...)`** calldata so the proxy’s constructor performs the initializer delegatecall before the deployment transaction ends.
* A **proxy factory** (or deployer helper) whose single entrypoint **`deploy`s** the proxy and **`call`s** `initialize` on the new address in the **same transaction** (any revert aborts the whole deploy; no orphan uninitialized proxy from that path).

Explicit runbook:

1. Deploy **implementation** (never call user‑facing `initialize` on the implementation in production unless you mean to brick or document a pattern—follow OZ guidance).
2. Create the **proxy** using a pattern where **`initialize`** runs **in the same transaction** as proxy creation, with owner, broadcaster, recovery, timelock, and `eventForwarder` (match your concrete contract’s arity and order). Do **not** rely on a follow‑up transaction to initialize a proxy that is already callable at its deployed address.
3. **Only after** that atomic creation+initialization transaction succeeds, run smoke‑reads on the **proxy**: **`owner()`**, **`getRecovery()`**, **`getTimeLockPeriodSec()`**, and verify **`eventForwarder`** matches your intent—before funding, granting roles, or sending production traffic.

More detail: [Best Practices — Deployment](/protocol/best-practices.md) (initializer subsection under Deployment) and [Account Pattern](/protocol/account-pattern.md).

***

## 🔒 **Security Basics**

Keep these minimum practices in your integration:

```typescript
// 1) Environment-based secrets
const PRIVATE_KEY = process.env.PRIVATE_KEY;
if (!PRIVATE_KEY) throw new Error('PRIVATE_KEY env var is required');

// 2) Simple address validation
const isAddress = (value: string) => /^0x[a-fA-F0-9]{40}$/.test(value);

// 3) Error handling around writes
try {
  const result = await secureOwnable.transferOwnershipRequest({ from: account.address });
  console.log('Tx hash:', result.hash);
} catch (error) {
  console.error('Tx failed:', error);
}
```

For a full set of recommendations, see [Best Practices](/protocol/best-practices.md).

***

## 🧪 **Protocol development (internal test chain)**

The repo includes **internal** scripts for running sanity tests against a local JSON-RPC node (often called `remote_evm` in `deployed-addresses.json`). This is **not** part of the published protocol surface integrators should rely on.

For protocol maintainers only:

1. Copy `env.example` to `.env` (or run `npm run generate:sanity-env -- --out .env` after an internal deploy).
2. Deploy the internal test stack: `npm run deploy:remote-evm:test`
3. Run Foundry: `npm run test:foundry`; optional SDK sanity: `npm run test:sanity-sdk:core`

Integrators should use **public testnets** (e.g. sepolia) and addresses from `deployed-addresses.json` with the SDK — not hard-coded role or wallet profiles from sanity tooling.

***

## 📚 **Next Steps**

1. Learn more about the [Account Pattern](/protocol/account-pattern.md) and how it composes the core components.
2. Explore component‑level docs:
   * [SecureOwnable](/protocol/secure-ownable.md)
   * [RuntimeRBAC](/protocol/runtime-rbac.md)
   * [GuardController](/protocol/guard-controller.md)
3. Dive into architecture:
   * [Bloxchain Architecture](/protocol/bloxchain-architecture.md)
   * [State Machine Engine](/protocol/state-machine-engine.md)
   * [Core Contract Graph](/protocol/core-contract-graph.md)
4. Look at end‑to‑end flows in [Basic Examples](/protocol/examples-basic.md).

For detailed API signatures, see the [API Reference](/protocol/api-reference.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.bloxchain.app/protocol/getting-started.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
