# Smart contract development with Blueprint (https://docs-fpm2731fy-ton-core-docs.vercel.app/llms/contract-dev/blueprint/develop/content.md)



<Callout type="note">
  [Acton](/llms/contract-dev/acton/content.md) is the recommended tool for new smart contract projects. Blueprint remains supported for existing projects.
</Callout>

Ensure your current directory is the root of the project initialized with `npm create ton@latest`.

## Contract creation [#contract-creation]

Use Blueprint to create a new contract.

### Interactive mode [#interactive-mode]

To launch a guided prompt to create a contract step by step, use:

```bash
npx blueprint create
```

### Non-interactive mode [#non-interactive-mode]

To create a contract without prompts, provide the contract name and template type:

```bash
npx blueprint create <CONTRACT> --type <TYPE>
```

* `<CONTRACT>`- contract name
* `<TYPE>`- template type, e.g., tolk-empty, func-empty, tolk-counter, func-counter

**Example:**

```bash
npx blueprint create MyNewContract --type tolk-empty
```

## Contract code writing [#contract-code-writing]

After creation, contracts are placed in the `contracts/` folder.
Each file uses the extension that matches its language.
For example, creating a Tolk contract `MyNewContract` results in `contracts/my_new_contract.tolk`.

## Building [#building]

Blueprint compiles your contracts into build artifacts.

### Interactive mode [#interactive-mode-1]

Run without arguments to select contracts from a prompt:

```bash
npx blueprint build
```

### Non-interactive mode [#non-interactive-mode-1]

Specify a contract name or use flags to skip prompts:

```bash
npx blueprint build <CONTRACT>
```

**Example:**

```bash
npx blueprint build MyNewContract
npx blueprint build --all # build all contracts
```

### Compiled artifacts [#compiled-artifacts]

Compiled outputs are stored in the `build/` directory.

* `build/<CONTRACT>.compiled.json`- serialized contract representation used for deployment and testing.

  Each file contains three fields:

  * `hash` — hash of the compiled contract code in hexadecimal format.
  * `hashBase64`  — the same hash encoded in Base64.
  * `hex` — the compiled contract code in hexadecimal form.

  Example:

  ```json title='<CONTRACT>.compiled.json'
  {
      "hash":"21eabd3331276c532778ad3fdcb5b78e5cf2ffefbc0a6dc...",
      "hashBase64":"Ieq9MzEnbFMneK0/3LW3jlzy/++8Cm3Dxkt+I3yRe...",
      "hex":"b5ee9c72410106010082000114ff00f4a413f4bcf2c80b01..."
  }
  ```

* `build/<CONTRACT>/<CONTRACT>.fif` — Fift code derived from the contract.

## Wrappers [#wrappers]

Wrappers are TypeScript classes that **you write** to interact with your smart contracts. They act as a bridge between your application code and the blockchain, encapsulating contract deployment, message sending, and data retrieval logic. Each wrapper implements the `Contract` interface from [`@ton/core`](https://github.com/ton-org/ton-core).

When you create a new contract with Blueprint, you need to write your own wrapper class in the `wrappers/` folder to define how your application will interact with the contract.

<Callout type="tip" title="Naming Convention">
  Methods that send messages should start with `send` (e.g., `sendDeploy`, `sendIncrement`), and methods that read data should start with `get` (e.g., `getCounter`).

  This convention works seamlessly with the `open()` method, which automatically provides the `ContractProvider` as the first argument to your wrapper methods.
</Callout>

### Static creating methods [#static-creating-methods]

Wrappers typically include two main static methods for creating contract instances:

#### `createFromAddress(address: Address)` [#createfromaddressaddress-address]

Creates a wrapper instance for an **already deployed** contract using its address. This method is used when you want to interact with an existing contract on the blockchain.

```typescript title="./wrappers/Counter.ts"
import { Address, Cell, Contract } from '@ton/core';

export class Counter implements Contract {
    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}

    static createFromAddress(address: Address) {
        return new Counter(address);
    }
}
```

#### `createFromConfig(config, code, workchain)` [#createfromconfigconfig-code-workchain]

Creates a wrapper instance for a **new contract** that hasn't been deployed yet. This method calculates the contract's future address based on its initial state and code.

```typescript title="./wrappers/Counter.ts"
import { Address, beginCell, Cell, Contract, contractAddress } from '@ton/core';

export type CounterConfig = {
    id: number;
    counter: number;
};

export function counterConfigToCell(config: CounterConfig): Cell {
    return beginCell().storeUint(config.id, 32).storeUint(config.counter, 32).endCell();
}

export class Counter implements Contract {
    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}

    static createFromConfig(config: CounterConfig, code: Cell, workchain = 0) {
        const data = counterConfigToCell(config);
        const init = { code, data };
        return new Counter(contractAddress(workchain, init), init);
    }
}
```

**Parameters:**

* `config` - Initial configuration data for your contract
* `code` - Compiled contract code (usually loaded from build artifacts)
* `workchain` - workchain ID (0 for basechain, -1 for masterchain)

<Callout type="tip">
  Contracts created with `createFromAddress()` cannot be deployed since they lack the `init` data required for deployment. Use `createFromConfig()` for new contracts that need to be deployed.
</Callout>

### Sending messages [#sending-messages]

Message sending methods allow your application to trigger contract execution by sending [internal or external messages](/llms/foundations/messages/ordinary-tx/content.md). These methods handle the construction of message bodies and transaction parameters.

All sending methods follow a similar pattern and should start with `send`:

```typescript title="./wrappers/Counter.ts"
import { ContractProvider, Sender, SendMode, beginCell, Cell } from '@ton/core';

export class Counter implements Contract {
    async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
        await provider.internal(via, {
            value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body: beginCell().endCell(), // empty body for deployment
        });
    }

    async sendIncrement(provider: ContractProvider, via: Sender, opts: { value: bigint; queryId?: number }) {
        await provider.internal(via, {
            value: opts.value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body: beginCell()
                .storeUint(0x7e8764ef, 32) // opcode for increment
                .storeUint(opts.queryId ?? 0, 64) // queryId
                .endCell(),
        });
    }

    async sendExternal(provider: ContractProvider, body: Cell) {
        await provider.external(body);
    }
}
```

**Parameters:**

* `provider` - `ContractProvider` instance that handles blockchain communication
* `via` - `Sender` object representing the transaction sender
* `opts` - Options object containing transaction value and method-specific parameters

### Calling get methods [#calling-get-methods]

Get methods allow you to read data from smart contracts without creating transactions. These methods are read-only operations that query the contract's current state.

All get methods should start with `get` and return a Promise:

```typescript title="./wrappers/Counter.ts"
import { Contract, ContractProvider } from '@ton/core';

export class Counter implements Contract {

    async getCounter(provider: ContractProvider): Promise<number> {
        const result = await provider.get('currentCounter', []);
        return result.stack.readNumber();
    }

    async getItemById(provider: ContractProvider, id: number): Promise<number> {
        const result = await provider.get('itemById', [
            { type: 'int', value: BigInt(id) }
        ]);
        return result.stack.readNumber();
    }

    async getContractData(provider: ContractProvider): Promise<{ counter: number; id: number }> {
        const result = await provider.get('contractData', []);
        return {
            counter: result.stack.readNumber(),
            id: result.stack.readNumber(),
        };
    }
}
```

### Complete example [#complete-example]

```typescript title="./wrappers/Counter.ts" expandable
import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';

export type NewContractConfig = {
    id: number;
    counter: number;
};

export function newContractConfigToCell(config: NewContractConfig): Cell {
    return beginCell().storeUint(config.id, 32).storeUint(config.counter, 32).endCell();
}

export const Opcodes = {
    OP_INCREASE: 0x7e8764ef,
    OP_RESET: 0x3a752f06,
};

export class NewContract implements Contract {
    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}

    static createFromAddress(address: Address) {
        return new NewContract(address);
    }

    static createFromConfig(config: NewContractConfig, code: Cell, workchain = 0) {
        const data = newContractConfigToCell(config);
        const init = { code, data };
        return new NewContract(contractAddress(workchain, init), init);
    }

    async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
        await provider.internal(via, {
            value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body: beginCell().endCell(),
        });
    }

    async sendIncrease(
        provider: ContractProvider,
        via: Sender,
        opts: {
            increaseBy: number;
            value: bigint;
            queryID?: number;
        }
    ) {
        await provider.internal(via, {
            value: opts.value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body: beginCell()
                .storeUint(Opcodes.OP_INCREASE, 32)
                .storeUint(opts.queryID ?? 0, 64)
                .storeUint(opts.increaseBy, 32)
                .endCell(),
        });
    }

    async sendReset(
        provider: ContractProvider,
        via: Sender,
        opts: {
            value: bigint;
            queryID?: number;
        }
    ) {
        await provider.internal(via, {
            value: opts.value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body: beginCell()
                .storeUint(Opcodes.OP_RESET, 32)
                .storeUint(opts.queryID ?? 0, 64)
                .endCell(),
        });
    }

    async getCounter(provider: ContractProvider) {
        const result = await provider.get('currentCounter', []);
        return result.stack.readNumber();
    }

    async getID(provider: ContractProvider) {
        const result = await provider.get('initialId', []);
        return result.stack.readNumber();
    }
}
```

## Testing [#testing]

To test contracts, follow the [Smart contract testing](/llms/contract-dev/testing/overview/content.md).

## Deployment [#deployment]

To deploy contracts, follow the [Deployment and interaction](/llms/contract-dev/blueprint/deploy/content.md) section.
