Skip to content

Commit ae69708

Browse files
committed
tact flow
1 parent 65d7c0f commit ae69708

File tree

6 files changed

+50
-76
lines changed

6 files changed

+50
-76
lines changed

docs/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/deploying-to-network.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Now that our smart contracts are fully tested, we are ready to deploy them to TO
5757
Deployment scripts rely on the same wrappers that you have used in testing scripts. We will use one common script to deploy both of the previously deployed smart contracts. Update `deployHelloWorld.ts` with this code:
5858

5959
```typescript title="/scripts/deployHelloWorld.ts"
60+
@version TypeScript 5.8.3
6061
import { toNano } from '@ton/core';
6162
import { HelloWorld } from '../wrappers/HelloWorld';
6263
import { compile, NetworkProvider } from '@ton/blueprint';

docs/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/processing-messages.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ async sendExternalIncrease(
311311
Update the test to ensure that the `HelloWorld` contract received the external message, and updated its counters:
312312

313313
```typescript title="/tests/HelloWorld.spec.ts"
314+
@version TypeScript 5.8.3
314315
import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';
315316
import { Cell, toNano} from '@ton/core';
316317
import { HelloWorld } from '../wrappers/HelloWorld';

docs/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/storage-and-get-methods.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ Next, we'll update our wrapper class to align with the new storage layout and `g
408408
These changes will maintain consistency with our smart contract modifications.
409409

410410
```typescript title="/wrappers/HelloWorld.ts"
411+
@version TypeScript 5.8.3
411412
export type HelloWorldConfig = {
412413
id: number;
413414
ctxCounter: number;
@@ -446,6 +447,7 @@ Finally, let's test the new functionality using our updated wrapper:
446447
Example implementation:
447448

448449
```typescript title="/tests/HelloWorld.spec.ts"
450+
@version TypeScript 5.8.3
449451
import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';
450452
import { Cell, toNano} from '@ton/core';
451453
import { HelloWorld } from '../wrappers/HelloWorld';

docs/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-blueprint-sdk-overview.mdx

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ If you didn't choose the proposed names in the previous steps, source code file
1515
:::
1616

1717
<Tabs groupId="language">
18-
<TabItem value="FunC" label="FunC">
18+
<TabItem value="Tact" label="Tact">
1919
```ls title="Project structure"
2020
Example/
2121
├── contracts/ # Folder containing smart contracts code
22-
│ ├── imports/ # Library imports for contracts
23-
│ │ └── stdlib.fc # Standard library for FunC
24-
│ └── hello_world.fc # Main contract file
22+
│ ├── hello_world.tact # Main contract file
2523
├── scripts/ # Deployment and on-chain interaction scripts
2624
│ ├── deployHelloWorld.ts # Script to deploy the contract
2725
│ └── incrementHelloWorld.ts # Script to interact with the contract
@@ -32,21 +30,7 @@ If you didn't choose the proposed names in the previous steps, source code file
3230
└── HelloWorld.compile.ts # Script for contract compilation
3331
```
3432
</TabItem>
35-
<TabItem value="Tolk" label="Tolk">
36-
```ls title="Project structure"
37-
Example/
38-
├── contracts/ # Folder containing smart contracts code
39-
│ └── hello_world.tolk # Main contract file
40-
├── scripts/ # Deployment and on-chain interaction scripts
41-
│ ├── deployHelloWorld.ts # Script to deploy the contract
42-
│ └── incrementHelloWorld.ts # Script to interact with the contract
43-
├── tests/ # Test fo der for local contract testing
44-
│ └── HelloWorld.spec.ts # Test specifications for the contract
45-
└── wrappers/ # TypeScript wrappers for contract interaction
46-
├── HelloWorld.ts # Wrapper class for smart contract
47-
└── HelloWorld.compile.ts # Script for contract compilation
48-
```
49-
</TabItem>
33+
5034
</Tabs>
5135

5236
### `/contracts`

docs/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-deploying-to-network.mdx

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -59,42 +59,27 @@ Deployment scripts rely on the same wrappers that you have used in testing scrip
5959
```typescript title="/scripts/deployHelloWorld.ts"
6060
import { toNano } from '@ton/core';
6161
import { HelloWorld } from '../wrappers/HelloWorld';
62-
import { CounterInternal } from '../wrappers/CounterInternal';
6362
import { compile, NetworkProvider } from '@ton/blueprint';
6463

6564
export async function run(provider: NetworkProvider) {
66-
const helloWorld = provider.open(
67-
HelloWorld.createFromConfig(
68-
{
69-
id: Math.floor(Math.random() * 10000),
70-
ctxCounter: 0,
71-
ctxCounterExt: 0n,
72-
},
73-
await compile('HelloWorld')
74-
)
75-
);
65+
const sender = provider.sender();
66+
if (!sender.address) {
67+
throw new Error('Sender address is required');
68+
}
7669

77-
await helloWorld.sendDeploy(provider.sender(), toNano('0.05'));
78-
79-
await provider.waitForDeploy(helloWorld.address);
80-
81-
const counterInternal = provider.open(
82-
await CounterInternal.fromInit(
83-
BigInt(Math.floor(Math.random() * 10000)),
84-
helloWorld.address
85-
)
70+
const helloWorld = provider.open(
71+
await HelloWorld.fromInit(0n, sender.address)
8672
);
8773

88-
await counterInternal.send(
89-
provider.sender(),
74+
await helloWorld.send(
75+
sender,
9076
{ value: toNano('0.05') },
9177
null
9278
);
9379

94-
await provider.waitForDeploy(counterInternal.address);
80+
await provider.waitForDeploy(helloWorld.address);
9581

96-
console.log('ID', await helloWorld.getID());
97-
console.log('ID', (await counterInternal.getId()).toString());
82+
console.log('ID', await helloWorld.getId());
9883
}
9984
```
10085

docs/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-storage-and-get-methods.mdx

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Using this structure, a message can be sent to the contract from FunC.
6060
The [contract](https://docs.tact-lang.org/book/contracts/) definition in Tact follows an object-oriented programming style:
6161

6262
```tact
63-
contract CounterInternal {
63+
contract HelloWorld {
6464
...
6565
}
6666
```
@@ -76,7 +76,7 @@ counter: Int as uint32;
7676

7777
To ensure that only the contract owner can interact with specific functions, add an `owner` field:
7878

79-
```tact title="/contracts/counter_internal.tact"
79+
```tact title="/contracts/hello_world.tact"
8080
id: Int as uint32;
8181
counter: Int as uint32;
8282
owner: Address;
@@ -88,7 +88,7 @@ These fields are serialized similarly to structures and stored in the contract's
8888

8989
If you compile the contract at this stage, you will encounter the error: `Field "owner" is not set`. This is because the contract needs to initialize its fields upon deployment. Define an [`init()`](https://docs.tact-lang.org/book/contracts/#init-function/) function to do this:
9090

91-
```tact title="/contracts/counter_internal.tact"
91+
```tact title="/contracts/hello_world.tact"
9292
init(id: Int, owner: Address) {
9393
self.id = id;
9494
self.counter = 0;
@@ -100,7 +100,7 @@ init(id: Int, owner: Address) {
100100

101101
To accept messages from other contracts, use a [receiver](https://docs.tact-lang.org/book/functions/#receiver-functions) function. Receiver functions automatically match the message's opcode and invoke the corresponding function:
102102

103-
```tact title="/contracts/counter_internal.tact"
103+
```tact title="/contracts/hello_world.tact"
104104
receive(msg: Add) {
105105
self.counter += msg.amount;
106106
self.notify("Cashback".asComment());
@@ -109,7 +109,7 @@ receive(msg: Add) {
109109

110110
For accepting messages with empty body you can add `recieve` function with no arguments:
111111

112-
```tact title="/contracts/counter_internal.tact"
112+
```tact title="/contracts/hello_world.tact"
113113
receive() {
114114
cashback(sender())
115115
}
@@ -120,7 +120,7 @@ receive() {
120120

121121
Tact also provides handy ways to share same logic through [traits](https://docs.tact-lang.org/book/types/#traits). To ensure that only the contract owner can send messages, use the `Ownable` trait, which provides built-in ownership checks:
122122

123-
```tact title="/contracts/counter_internal.tact"
123+
```tact title="/contracts/hello_world.tact"
124124
// Import library to use trait
125125
import "@stdlib/ownable";
126126
@@ -149,7 +149,7 @@ Tact supports [getter functions](https://docs.tact-lang.org/book/functions/#gett
149149
Get function cannot be called from another contract.
150150
:::
151151

152-
```tact title="/contracts/counter_internal.tact"
152+
```tact title="/contracts/hello_world.tact"
153153
get fun counter(): Int {
154154
return self.counter;
155155
}
@@ -159,7 +159,7 @@ Note, that the `owner` getter is automatically defined via the `Ownable` trait.
159159

160160
#### Complete contract
161161

162-
```tact title="/contracts/counter_internal.tact"
162+
```tact title="/contracts/hello_world.tact"
163163
import "@stdlib/ownable";
164164
165165
// message with opcode
@@ -169,7 +169,7 @@ message(0x7e8764ef) Add {
169169
}
170170
171171
// Contract defenition. `Ownable` is a trait to share functionality.
172-
contract CounterInternal with Ownable {
172+
contract HelloWorld with Ownable {
173173
174174
// storage variables
175175
id: Int as uint32;
@@ -233,7 +233,7 @@ Expected output should look like this:
233233

234234
[Wrappers](https://docs.tact-lang.org/book/compile/#wrap-ts) facilitate contract interaction from TypeScript. Unlike in FunC or Tolk, they are generated automatically during the build process:
235235

236-
```typescript title="/wrappers/CounterInternal.ts"
236+
```typescript title="/wrappers/HelloWorld.ts"
237237
export * from '../build/CounterInternal/tact_CounterInternal';
238238
```
239239

@@ -246,15 +246,15 @@ Now let's ensure that our smart contract code fails when we try to send `add` me
246246

247247
Implementation of test should look like this:
248248

249-
```typescript title="/tests/CounterInternal.spec.ts"
249+
```typescript title="/tests/HelloWorld.spec.ts"
250250
import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';
251251
import { toNano } from '@ton/core';
252-
import { CounterInternal } from '../wrappers/CounterInternal';
252+
import { HelloWorld } from '../wrappers/HelloWorld';
253253
import '@ton/test-utils';
254254

255-
describe('CounterInternal Basic Tests', () => {
255+
describe('HelloWorld Basic Tests', () => {
256256
let blockchain: Blockchain;
257-
let counterInternal: SandboxContract<CounterInternal>;
257+
let helloWorld: SandboxContract<HelloWorld >;
258258
let owner: SandboxContract<TreasuryContract>;
259259

260260
beforeEach(async () => {
@@ -265,12 +265,12 @@ describe('CounterInternal Basic Tests', () => {
265265
owner = await blockchain.treasury('owner');
266266

267267
// Deploy the contract
268-
counterInternal = blockchain.openContract(
269-
await CounterInternal.fromInit(0n, owner.address)
268+
helloWorld = blockchain.openContract(
269+
await HelloWorld .fromInit(0n, owner.address)
270270
);
271271

272272
// Send deploy transaction
273-
const deployResult = await counterInternal.send(
273+
const deployResult = await helloWorld.send(
274274
owner.getSender(),
275275
{ value: toNano('1.00') },
276276
null
@@ -279,29 +279,29 @@ describe('CounterInternal Basic Tests', () => {
279279
// Verify deployment was successful
280280
expect(deployResult.transactions).toHaveTransaction({
281281
from: owner.address,
282-
to: counterInternal.address,
282+
to: helloWorld.address,
283283
deploy: true,
284284
success: true
285285
});
286286
});
287287

288288
it('should initialize with correct values', async () => {
289289
// Check initial counter value
290-
const initialCounter = await counterInternal.getCounter();
290+
const initialCounter = await helloWorld.getCounter();
291291
expect(initialCounter).toBe(0n);
292292

293293
// Check initial ID
294-
const id = await counterInternal.getId();
294+
const id = await helloWorld.getId();
295295
expect(id).toBe(0n);
296296
});
297297

298298
it('should allow owner to increment counter', async () => {
299299
// Get initial counter value
300-
const initialCounter = await counterInternal.getCounter();
300+
const initialCounter = await helloWorld.getCounter();
301301

302302
// Increment counter by 5
303303
const incrementAmount = 5n;
304-
const result = await counterInternal.send(
304+
const result = await helloWorld.send(
305305
owner.getSender(),
306306
{ value: toNano('0.05') },
307307
{
@@ -314,12 +314,12 @@ describe('CounterInternal Basic Tests', () => {
314314
// Verify transaction was successful
315315
expect(result.transactions).toHaveTransaction({
316316
from: owner.address,
317-
to: counterInternal.address,
317+
to: helloWorld.address,
318318
success: true
319319
});
320320

321321
// Check counter was incremented correctly
322-
const newCounter = await counterInternal.getCounter();
322+
const newCounter = await helloWorld.getCounter();
323323
expect(newCounter).toBe(initialCounter + incrementAmount);
324324
});
325325

@@ -328,10 +328,10 @@ describe('CounterInternal Basic Tests', () => {
328328
const nonOwner = await blockchain.treasury('nonOwner');
329329

330330
// Get initial counter value
331-
const initialCounter = await counterInternal.getCounter();
331+
const initialCounter = await helloWorld.getCounter();
332332

333333
// Try to increment counter as non-owner
334-
const result = await counterInternal.send(
334+
const result = await helloWorld.send(
335335
nonOwner.getSender(),
336336
{ value: toNano('0.05') },
337337
{
@@ -344,12 +344,12 @@ describe('CounterInternal Basic Tests', () => {
344344
// Verify transaction failed
345345
expect(result.transactions).toHaveTransaction({
346346
from: nonOwner.address,
347-
to: counterInternal.address,
347+
to: helloWorld.address,
348348
success: false
349349
});
350350

351351
// Verify counter was not changed
352-
const newCounter = await counterInternal.getCounter();
352+
const newCounter = await helloWorld.getCounter();
353353
expect(newCounter).toBe(initialCounter);
354354
});
355355

@@ -359,7 +359,7 @@ describe('CounterInternal Basic Tests', () => {
359359
let expectedCounter = 0n;
360360

361361
for (const amount of increments) {
362-
await counterInternal.send(
362+
await helloWorld.send(
363363
owner.getSender(),
364364
{ value: toNano('0.05') },
365365
{
@@ -372,11 +372,12 @@ describe('CounterInternal Basic Tests', () => {
372372
}
373373

374374
// Verify final counter value
375-
const finalCounter = await counterInternal.getCounter();
375+
const finalCounter = await helloWorld.getCounter();
376376
expect(finalCounter).toBe(expectedCounter);
377377
});
378378
});
379379

380+
380381
```
381382

382383
Don't forget to verify the example is correct by running test script:
@@ -389,8 +390,8 @@ Expected output should look like this:
389390

390391
```bash
391392

392-
PASS tests/CounterInternal.spec.ts
393-
CounterInternal Basic Tests
393+
PASS tests/HelloWorld.spec.ts
394+
HelloWorld Basic Tests
394395
✓ should initialize with correct values (211 ms)
395396
✓ should allow owner to increment counter (100 ms)
396397
✓ should prevent non-owner from incrementing counter (152 ms)

0 commit comments

Comments
 (0)