Skip to content

Commit 1a37207

Browse files
committed
midpoint
1 parent 40c928c commit 1a37207

File tree

3 files changed

+172
-171
lines changed

3 files changed

+172
-171
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Button from '@site/src/components/button'
1111
If you're stuck on any of the examples, you can find the original template project with all modifications made during this guide [here](https://github.com/ton-community/onboarding-sandbox/tree/main/quick-start/smart-contracts/Example/contracts).
1212
:::
1313

14-
Almost all smart contracts need to store their `data` between transactions. This guide explains standard ways to manage `storage` for smart contracts and how to use `get methods` to access it from outside the blockchain.
14+
Almost all smart contracts need to store their `data` between transactions. This guide explains standard ways to manage `storage` for smart contracts and how to use `get methods` to access it outside the blockchain.
1515

1616
## Smart contract storage operations
1717

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

Lines changed: 170 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ import Button from '@site/src/components/button'
55

66
# Storage and get methods
77

8-
> **Summary:** In the previous steps, we learned how to use the `Blueprint` and its project structure.
8+
> **Summary:** In the previous steps, we learned how to use the `Blueprint SDK` and its project structure.
99
1010
:::info
1111
For more details, refer to the [Tact documentation](https://docs.tact-lang.org/#start/) and [Tact By Example](https://tact-by-example.org/00-hello-world/).
1212
:::
1313

14-
Let's create and modify our smart contract following standard steps described in the previous [Blueprint overview](/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-blueprint-sdk-overview/) section.
14+
15+
Smart contracts often need to store data, like counters or ownership information, and provide a way to read or update it through messages. In this section, you’ll learn how to define and initialize contract storage, receive and handle incoming messages, restrict access using traits, and create getter functions to read contract states outside the blockchain.
16+
17+
Let's create and modify our smart contract following the standard steps described in the previous [Blueprint overview](/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-blueprint-sdk-overview/) section.
18+
1519

1620
## Step 1: edit smart contract code
1721

@@ -78,26 +82,16 @@ A contract may store its state variables as follows. They may be accessed with [
7882
id: Int as uint32;
7983
counter: Int as uint32;
8084
```
81-
82-
To ensure that only the contract owner can interact with specific functions, add an `owner` field:
83-
84-
```tact title="/contracts/hello_world.tact"
85-
id: Int as uint32;
86-
counter: Int as uint32;
87-
owner: Address;
88-
```
89-
9085
These fields are serialized similarly to structures and stored in the contract's data register.
9186

9287
#### Initializing the contract
9388

94-
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:
89+
Define an [`init()`](https://docs.tact-lang.org/book/contracts/#init-function/) function to do this:
9590

9691
```tact title="/contracts/hello_world.tact"
9792
init(id: Int, owner: Address) {
9893
self.id = id;
9994
self.counter = 0;
100-
self.owner = owner;
10195
}
10296
```
10397

@@ -248,174 +242,181 @@ This code exports everything inside the `tact_HelloWorld.ts` file in the build f
248242

249243
## Step 3: updating tests
250244

251-
Now let's ensure that our smart contract code fails when we try to send `add` message from non-owner:
252-
- Create `HelloWorld` with some owner.
253-
- Create another smart contract that will have different address - `nonOwner`.
254-
- Try to send an internal message to `HelloWorld` and enusre that it fails with expected `exitCode` and counter field remains the same.
255-
256-
Implementation of test should look like this:
257-
258-
```typescript title="/tests/HelloWorld.spec.ts"
259-
// @version TypeScript 5.8.3
260-
import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';
261-
import { toNano } from '@ton/core';
262-
import { HelloWorld } from '../wrappers/HelloWorld';
263-
import '@ton/test-utils';
264-
265-
describe('HelloWorld Basic Tests', () => {
266-
let blockchain: Blockchain;
267-
let helloWorld: SandboxContract<HelloWorld >;
268-
let owner: SandboxContract<TreasuryContract>;
269-
270-
beforeEach(async () => {
271-
// Create a new blockchain instance
272-
blockchain = await Blockchain.create();
273-
274-
// Create an owner wallet
275-
owner = await blockchain.treasury('owner');
276-
277-
// Deploy the contract
278-
helloWorld = blockchain.openContract(
279-
await HelloWorld .fromInit(0n, owner.address)
280-
);
281-
282-
// Send deploy transaction
283-
const deployResult = await helloWorld.send(
284-
owner.getSender(),
285-
{ value: toNano('1.00') },
286-
null
287-
);
288-
289-
// Verify deployment was successful
290-
expect(deployResult.transactions).toHaveTransaction({
291-
from: owner.address,
292-
to: helloWorld.address,
293-
deploy: true,
294-
success: true
295-
});
296-
});
297-
298-
it('should initialize with correct values', async () => {
299-
// Check initial counter value
300-
const initialCounter = await helloWorld.getCounter();
301-
expect(initialCounter).toBe(0n);
302-
303-
// Check initial ID
304-
const id = await helloWorld.getId();
305-
expect(id).toBe(0n);
306-
});
307-
308-
it('should allow owner to increment counter', async () => {
309-
// Get initial counter value
310-
const initialCounter = await helloWorld.getCounter();
311-
312-
// Increment counter by 5
313-
const incrementAmount = 5n;
314-
const result = await helloWorld.send(
315-
owner.getSender(),
316-
{ value: toNano('0.05') },
317-
{
318-
$$type: 'Add',
319-
amount: incrementAmount,
320-
queryId: 0n
321-
}
322-
);
323-
324-
// Verify transaction was successful
325-
expect(result.transactions).toHaveTransaction({
326-
from: owner.address,
327-
to: helloWorld.address,
328-
success: true
329-
});
330-
331-
// Check counter was incremented correctly
332-
const newCounter = await helloWorld.getCounter();
333-
expect(newCounter).toBe(initialCounter + incrementAmount);
334-
});
335-
336-
it('should prevent non-owner from incrementing counter', async () => {
337-
// Create a non-owner wallet
338-
const nonOwner = await blockchain.treasury('nonOwner');
339-
340-
// Get initial counter value
341-
const initialCounter = await helloWorld.getCounter();
342-
343-
// Try to increment counter as non-owner
344-
const result = await helloWorld.send(
345-
nonOwner.getSender(),
346-
{ value: toNano('0.05') },
347-
{
348-
$$type: 'Add',
349-
amount: 5n,
350-
queryId: 0n
351-
}
352-
);
353-
354-
// Verify transaction failed
355-
expect(result.transactions).toHaveTransaction({
356-
from: nonOwner.address,
357-
to: helloWorld.address,
358-
success: false
359-
});
360-
361-
// Verify counter was not changed
362-
const newCounter = await helloWorld.getCounter();
363-
expect(newCounter).toBe(initialCounter);
364-
});
365-
366-
it('should handle multiple increments correctly', async () => {
367-
// Perform multiple increments
368-
const increments = [3n, 7n, 2n];
369-
let expectedCounter = 0n;
370-
371-
for (const amount of increments) {
372-
await helloWorld.send(
373-
owner.getSender(),
374-
{ value: toNano('0.05') },
375-
{
376-
$$type: 'Add',
377-
amount: amount,
378-
queryId: 0n
379-
}
380-
);
381-
expectedCounter += amount;
382-
}
383-
384-
// Verify final counter value
385-
const finalCounter = await helloWorld.getCounter();
386-
expect(finalCounter).toBe(expectedCounter);
387-
});
245+
246+
<details>
247+
<summary><b>Updating tests</b></summary>
248+
249+
Now let's ensure that our smart contract code fails when we try to send `add` message from non-owner:
250+
- Create `HelloWorld` with some owner.
251+
- Create another smart contract that will have different address - `nonOwner`.
252+
- Try to send an internal message to `HelloWorld` and enusre that it fails with expected `exitCode` and counter field remains the same.
253+
254+
Implementation of test should look like this:
255+
256+
```typescript title="/tests/HelloWorld.spec.ts"
257+
// @version TypeScript 5.8.3
258+
import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';
259+
import { toNano } from '@ton/core';
260+
import { HelloWorld } from '../wrappers/HelloWorld';
261+
import '@ton/test-utils';
262+
263+
describe('HelloWorld Basic Tests', () => {
264+
let blockchain: Blockchain;
265+
let helloWorld: SandboxContract<HelloWorld >;
266+
let owner: SandboxContract<TreasuryContract>;
267+
268+
beforeEach(async () => {
269+
// Create a new blockchain instance
270+
blockchain = await Blockchain.create();
271+
272+
// Create an owner wallet
273+
owner = await blockchain.treasury('owner');
274+
275+
// Deploy the contract
276+
helloWorld = blockchain.openContract(
277+
await HelloWorld .fromInit(0n, owner.address)
278+
);
279+
280+
// Send deploy transaction
281+
const deployResult = await helloWorld.send(
282+
owner.getSender(),
283+
{ value: toNano('1.00') },
284+
null
285+
);
286+
287+
// Verify deployment was successful
288+
expect(deployResult.transactions).toHaveTransaction({
289+
from: owner.address,
290+
to: helloWorld.address,
291+
deploy: true,
292+
success: true
293+
});
388294
});
389295

296+
it('should initialize with correct values', async () => {
297+
// Check initial counter value
298+
const initialCounter = await helloWorld.getCounter();
299+
expect(initialCounter).toBe(0n);
390300

391-
```
301+
// Check initial ID
302+
const id = await helloWorld.getId();
303+
expect(id).toBe(0n);
304+
});
392305

393-
Don't forget to verify the example is correct by running test script:
306+
it('should allow owner to increment counter', async () => {
307+
// Get initial counter value
308+
const initialCounter = await helloWorld.getCounter();
394309

395-
```bash
396-
npx blueprint test
397-
```
310+
// Increment counter by 5
311+
const incrementAmount = 5n;
312+
const result = await helloWorld.send(
313+
owner.getSender(),
314+
{ value: toNano('0.05') },
315+
{
316+
$$type: 'Add',
317+
amount: incrementAmount,
318+
queryId: 0n
319+
}
320+
);
398321

399-
Expected output should look like this:
322+
// Verify transaction was successful
323+
expect(result.transactions).toHaveTransaction({
324+
from: owner.address,
325+
to: helloWorld.address,
326+
success: true
327+
});
400328

401-
```bash
329+
// Check counter was incremented correctly
330+
const newCounter = await helloWorld.getCounter();
331+
expect(newCounter).toBe(initialCounter + incrementAmount);
332+
});
333+
334+
it('should prevent non-owner from incrementing counter', async () => {
335+
// Create a non-owner wallet
336+
const nonOwner = await blockchain.treasury('nonOwner');
402337

403-
PASS tests/HelloWorld.spec.ts
338+
// Get initial counter value
339+
const initialCounter = await helloWorld.getCounter();
340+
341+
// Try to increment counter as non-owner
342+
const result = await helloWorld.send(
343+
nonOwner.getSender(),
344+
{ value: toNano('0.05') },
345+
{
346+
$$type: 'Add',
347+
amount: 5n,
348+
queryId: 0n
349+
}
350+
);
351+
352+
// Verify transaction failed
353+
expect(result.transactions).toHaveTransaction({
354+
from: nonOwner.address,
355+
to: helloWorld.address,
356+
success: false
357+
});
358+
359+
// Verify counter was not changed
360+
const newCounter = await helloWorld.getCounter();
361+
expect(newCounter).toBe(initialCounter);
362+
});
363+
364+
it('should handle multiple increments correctly', async () => {
365+
// Perform multiple increments
366+
const increments = [3n, 7n, 2n];
367+
let expectedCounter = 0n;
368+
369+
for (const amount of increments) {
370+
await helloWorld.send(
371+
owner.getSender(),
372+
{ value: toNano('0.05') },
373+
{
374+
$$type: 'Add',
375+
amount: amount,
376+
queryId: 0n
377+
}
378+
);
379+
expectedCounter += amount;
380+
}
381+
382+
// Verify final counter value
383+
const finalCounter = await helloWorld.getCounter();
384+
expect(finalCounter).toBe(expectedCounter);
385+
});
386+
});
387+
388+
389+
```
390+
391+
Don't forget to verify the example is correct by running test script:
392+
393+
```bash
394+
npx blueprint test
395+
```
396+
397+
Expected output should look like this:
398+
399+
```bash
400+
401+
PASS tests/HelloWorld.spec.ts
404402
HelloWorld Basic Tests
405-
✓ should initialize with correct values (211 ms)
406-
✓ should allow owner to increment counter (100 ms)
407-
✓ should prevent non-owner from incrementing counter (152 ms)
408-
✓ should handle multiple increments correctly (112 ms)
403+
✓ should initialize with correct values (211 ms)
404+
✓ should allow owner to increment counter (100 ms)
405+
✓ should prevent non-owner from incrementing counter (152 ms)
406+
✓ should handle multiple increments correctly (112 ms)
409407

410-
Test Suites: 1 passed, 1 total
411-
Tests: 4 passed, 4 total
412-
Snapshots: 0 total
413-
Time: 1.193 s, estimated 2 s
414-
Ran all test suites.
408+
Test Suites: 1 passed, 1 total
409+
Tests: 4 passed, 4 total
410+
Snapshots: 0 total
411+
Time: 1.193 s, estimated 2 s
412+
Ran all test suites.
415413

416-
```
414+
```
415+
416+
---
417+
418+
</details>
417419

418-
---
419420

420421
## Next step
421422

0 commit comments

Comments
 (0)