Skip to content

Contracts feedback #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Project structure
# Blueprint SDK overview

> **Summary:** In previous steps we installed and configured all tools required for TON smart-contract development and created our first project template.

Before we proceed to research and modification of smart-contract code, let's take a brief look at project structure, purpose of them and default scenarios of its use.
Before we proceed to actual smart-contract development let's briefly describe project structure and explain how to use **`Blueprint SDK`**.

## Overview
## Project structure

If you chose proposed names in previous steps your project structure should look like this:

<Tabs groupId="language">
<TabItem value="FunC" label="FunC">
```
```ls title="Project structure"
Example/
├── contracts/ # Folder containing smart contracts code
│ ├── imports/ # Library imports for contracts
Expand All @@ -30,7 +30,7 @@ Example/
```
</TabItem>
<TabItem value="Tolk" label="Tolk">
```
```ls title="Project structure"
Example/
├── contracts/ # Folder containing smart contracts code
│ └── hello_world.tolk # Main contract file
Expand All @@ -46,54 +46,52 @@ Example/
</TabItem>
</Tabs>

Before we proceed to actual smart-contract development let's briefly describe project structure and explain how to use **`Blueprint SDK`**.

### `/contracts`

This folder contains your smart contract source code written in one of the available programming languages used for TON blockchain smart contract development. And in case of `FunC` contains imports folder which is used for libraries usually containing `stdlib.fc` - standard library of `FunC` language.
This folder contains your smart contract source code written in one of the available programming languages used for TON blockchain smart contract development.

### `/wrappers`

- `HelloWorld.ts` - wrapper for smart contract.
- `HelloWorld.compile.ts` - compile config for smart-contract.
To interact with your smart-contract off-chain you need to serialize and desirialize messages sended to it. `Wrapper` classes developed to mirror your smart-contract implementation making it simple to use it's functionality.

While `@ton/ton SDK` provides us interfaces of serializing and sending messages for standard smart-contracts such as `wallets`, if we develop our own smart-contract that will deserialize received messages by its own custom protocol we need to provide some wrapper object that will serialize messages sent to smart-contract, deserialize responses from `get method`s and serialize `initial data` for contract deployment.

To run compile script excute this command in your CLI:
### `/tests`

```bash
npx blueprint build
```
This directory contains test files for your smart contracts. Testing contracts directly in TON network is not the best option because deployment requires some amount of time and may lead to losing funds. This testing playground allow you to execute multiple smart-contracts and even send messages between them in your **"local network"**. Tests are crucial for ensuring your smart contracts behave as expected before deployment to the network.

It's preferred development flow to edit smart contract code and then edit its wrapper correspondingly to updated protocol.
### `/scripts`

:::info Advanced, TL-B
Often, as a developer, you want to provide description of protocol by some formal language and TON ecosystem has standard instrument for that: [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) language. `TL-B`(Type Language-Binary) schemes serve to describe binary protocol of smart-contracts somewhat similar to **Protobuf** technology. At the current moment, unfortunately, there are no instruments that provide generation of serialization/deserialization interfaces, but it's anyway a good practice to have one for smart-contracts with complex interfaces.
:::
The scripts directory contains `TypeScript` files that help you deploy and interact with your smart contracts on-chain using previously implemented wrappers.

### `/tests`
## Development flow

This directory contains test files for your smart contracts, written using the **`Jest` testing framework**. It's testing playground that uses `@ton/sandbox` tool allowing you to execute multiple smart-contracts and even send messages between them, creating your local 'network' of contracts if your project requires so, and test more complex scenarios than simple **unit-tests**. Tests are crucial for ensuring your smart contracts behave as expected before deployment to the `Mainnet`.
Almost any smart-contract project development consist of five simple steps:

To run your test execute following command:
1. Edit smart-contract code in `/contracts` folder and build it by running build script:

```bash
npx blueprint build
```

Or use interface provided by `Jest` plugins in your **IDE** or **code-editor**.
2. Update smart-contract wrapper in `/wrapper` folder corresponding to changes in contract.
3. Update test's in `/tests` folder to ensure correctness of new functionality and run test script:

### `/scripts`
```bash
npx blueprint test
```

The scripts directory contains `TypeScript` files that help you deploy and interact with your smart contracts on-chain using previously implemented wrappers.
4. Repeat steps 1-3 until you get desired result.

You can execute those scripts using following command, but we recommend to read corresponding [deploying to netowrk](/v3/guidelines/quick-start/developing-smart-contracts/deploying-to-network) section first.
5. Update deployment script in `/scripts` folder and run it using this command:

```bash
npx blueprint run
npx blueprint run
```

Also, you can always generate same structure for another smart-contract if you need so, by using following command:
:::tip
All examples in this guide follow sequnce of this **1-3 steps** with corresponding code samples. **Step 5**, deployment process, is covered in last section of the guide: [Deploying to network](/v3/guidelines/quick-start/developing-smart-contracts/deploying-to-network).
:::

Also, you can always generate same structure for another smart-contract if, for example, you want to create multiple contracts interacting with each other, by using following command:

```bash
npx blueprint create PascalCase #dont forget to name contract in PascalCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ In this part of the guide we will proceed to deployment of previously developed

## Address and initial state

We already know that [address](/v3/documentation/smart-contracts/addresses/) is unique identifier of `smart-contract`, i.e `actor`, `account` in network which is used to send transactions and verify their sender upon receive but we still didn't discussed how it's created. The common formula of smart-contract address looks like that:
We already know that [address](/v3/documentation/smart-contracts/addresses/) is unique identifier of `smart-contract` in network which is used to send transactions and verify their sender upon receive, but we still didn't discussed how it's created. The common formula of smart-contract address looks like that:

***address=hash(state_init(code, data))***

Address of smart-contract is a hash of aggregated initial code and data of smart-contracts upon deployment. This simple mechanism have few important consequences:

### You already know the address

In TON any address that didn't accept any transaction and, as a consequnce, dont have any data is considered in `nonexzist` state, nethertheless when we created a wallet using wallet app in [Getting started](/v3/guidelines/quick-start/getting-started) section we still was able to get address of our **future** wallet smart-contract from wallet app before it's deployment and examine it in explorer.
In TON any address that don't have any data is considered in `nonexistent` state, nevertheless when we created a wallet using wallet app in [Getting started](/v3/guidelines/quick-start/getting-started) section we still was able to get address of our **future** wallet smart-contract from wallet app before it's deployment and examine it in explorer.

The reason behind that is because creating your private and public key pair through **mnemonic phrase**, where second key is part of initial data of smart-contract makes `state_init` of our contract fully determent:
The reason behind that is because creating your **private** and **public** key pair through **mnemonic phrase**, where second key is part of initial data of smart-contract makes `state_init` of our contract fully determent:
- **code** is one of the standard wallet implementation, like `v5r1`.
- **data** is `public_key` with other default initialized fields.

Expand All @@ -40,7 +40,7 @@ init(id: Int, owner: Address) {
}
```

If we remove `id` field from its initial storage we can ensure that **only one** `CounterInternal` smart-cotnract could exzist for a particular owner, moreover, if we consider owner as wallet smart-contract, by knowing its public_key and version we could calculate wallet address and, as a consequnce, address of its `CounterInternal` contract.
If we remove `id` field from its initial storage we can ensure that **only one** `CounterInternal` smart-cotnract could exzist for a particular owner.

:::info Tokens
This mechanism plays cruicial role in [Jetton Processing](v3/guidelines/dapps/asset-processing/jettons), each non-native(jetton) token requires it's own `Jetton Wallet` for a particular owner and therefore provides a calculatable address from it, creating a **star scheme** with basic wallet in center.
Expand All @@ -50,23 +50,19 @@ This mechanism plays cruicial role in [Jetton Processing](v3/guidelines/dapps/as

Now, when our smart-contracts is fully tested, we are ready to deploy them into the TON. In `Blueprint SDK` this process is the same for both `mainnet` and `testnet` and any of the presented languages in guide: `FunC`, `Tact`, `Tolk`. Deploy scripts relays on the same wrappers that you have used in testing scripts:

```typescript
```typescript title="/scripts/deployHelloWorld"
import { toNano } from '@ton/core';
import { HelloWorld } from '../wrappers/HelloWorld';
import { CounterInternal } from '../wrappers/CounterInternal';
import { compile, NetworkProvider } from '@ton/blueprint';
import { mnemonicToWalletKey } from '@ton/crypto';

export async function run(provider: NetworkProvider) {
const mnemonic = "".split(' '); // Insert your mnemonic
const { publicKey, secretKey } = await mnemonicToWalletKey(mnemonic);

const helloWorld = provider.open(
HelloWorld.createFromConfig(
{
id: Math.floor(Math.random() * 10000),
seqno: 0,
publicKey: publicKey
ctxCounter: 0,
ctxCounterExt: 0n,
},
await compile('HelloWorld')
)
Expand Down Expand Up @@ -99,6 +95,7 @@ export async function run(provider: NetworkProvider) {
console.log('ID', await helloWorld.getID());
console.log('ID', (await counterInternal.getId()).toString());
}

```

You can run those scripts by entering following command:
Expand Down
Loading