@btc-vision/btc-runtime 1.10.10 → 1.10.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +258 -137
  3. package/SECURITY.md +226 -0
  4. package/docs/README.md +614 -0
  5. package/docs/advanced/bitcoin-scripts.md +939 -0
  6. package/docs/advanced/cross-contract-calls.md +579 -0
  7. package/docs/advanced/plugins.md +1006 -0
  8. package/docs/advanced/quantum-resistance.md +660 -0
  9. package/docs/advanced/signature-verification.md +715 -0
  10. package/docs/api-reference/blockchain.md +729 -0
  11. package/docs/api-reference/events.md +642 -0
  12. package/docs/api-reference/op20.md +902 -0
  13. package/docs/api-reference/op721.md +819 -0
  14. package/docs/api-reference/safe-math.md +510 -0
  15. package/docs/api-reference/storage.md +840 -0
  16. package/docs/contracts/op-net-base.md +786 -0
  17. package/docs/contracts/op20-token.md +687 -0
  18. package/docs/contracts/op20s-signatures.md +614 -0
  19. package/docs/contracts/op721-nft.md +785 -0
  20. package/docs/contracts/reentrancy-guard.md +787 -0
  21. package/docs/core-concepts/blockchain-environment.md +724 -0
  22. package/docs/core-concepts/decorators.md +466 -0
  23. package/docs/core-concepts/events.md +652 -0
  24. package/docs/core-concepts/pointers.md +391 -0
  25. package/docs/core-concepts/security.md +473 -0
  26. package/docs/core-concepts/storage-system.md +969 -0
  27. package/docs/examples/basic-token.md +745 -0
  28. package/docs/examples/nft-with-reservations.md +1440 -0
  29. package/docs/examples/oracle-integration.md +1212 -0
  30. package/docs/examples/stablecoin.md +1180 -0
  31. package/docs/getting-started/first-contract.md +575 -0
  32. package/docs/getting-started/installation.md +384 -0
  33. package/docs/getting-started/project-structure.md +630 -0
  34. package/docs/storage/memory-maps.md +764 -0
  35. package/docs/storage/stored-arrays.md +778 -0
  36. package/docs/storage/stored-maps.md +758 -0
  37. package/docs/storage/stored-primitives.md +655 -0
  38. package/docs/types/address.md +773 -0
  39. package/docs/types/bytes-writer-reader.md +938 -0
  40. package/docs/types/calldata.md +744 -0
  41. package/docs/types/safe-math.md +446 -0
  42. package/package.json +51 -26
  43. package/runtime/memory/MapOfMap.ts +1 -0
  44. package/LICENSE.md +0 -21
@@ -0,0 +1,630 @@
1
+ # Project Structure
2
+
3
+ This guide explains the standard project structure for OPNet smart contract development and how the btc-runtime library is organized.
4
+
5
+ ## Your Project Structure
6
+
7
+ ### Project Directory Layout
8
+
9
+ This diagram visualizes the complete project structure and file relationships:
10
+
11
+ ```mermaid
12
+ ---
13
+ config:
14
+ theme: dark
15
+ ---
16
+ graph LR
17
+ subgraph root["Project Root"]
18
+ ROOT["my-opnet-project/"]
19
+ end
20
+
21
+ subgraph source["Source Code - src/"]
22
+ SRC["src/"]
23
+ TOKEN_DIR["token/"]
24
+ NFT_DIR["nft/"]
25
+
26
+ TOKEN["MyToken.ts"]
27
+ TOKEN_INDEX["index.ts"]
28
+ NFT["MyNFT.ts"]
29
+ NFT_INDEX["index.ts"]
30
+ end
31
+
32
+ subgraph build["Build Output - build/"]
33
+ BUILD["build/"]
34
+ TOKEN_WASM["MyToken.wasm"]
35
+ NFT_WASM["MyNFT.wasm"]
36
+ end
37
+
38
+ subgraph tests["Tests - tests/"]
39
+ TESTS["tests/"]
40
+ SPEC["MyToken.spec.ts"]
41
+ end
42
+
43
+ subgraph config["Configuration"]
44
+ ASCONFIG["asconfig.json"]
45
+ PKG["package.json"]
46
+ TSCONFIG["tsconfig.json"]
47
+ end
48
+
49
+ ROOT --> SRC
50
+ ROOT --> BUILD
51
+ ROOT --> TESTS
52
+ ROOT --> ASCONFIG
53
+ ROOT --> PKG
54
+ ROOT --> TSCONFIG
55
+
56
+ SRC --> TOKEN_DIR
57
+ SRC --> NFT_DIR
58
+
59
+ TOKEN_DIR --> TOKEN
60
+ TOKEN_DIR --> TOKEN_INDEX
61
+ NFT_DIR --> NFT
62
+ NFT_DIR --> NFT_INDEX
63
+
64
+ TOKEN -.->|"imported by"| TOKEN_INDEX
65
+ NFT -.->|"imported by"| NFT_INDEX
66
+
67
+ TOKEN_INDEX -.->|"compiled by"| ASCONFIG
68
+ NFT_INDEX -.->|"compiled by"| ASCONFIG
69
+ ASCONFIG -.->|"produces"| TOKEN_WASM
70
+ ASCONFIG -.->|"produces"| NFT_WASM
71
+
72
+ TOKEN -.->|"tested by"| SPEC
73
+ ```
74
+
75
+ A typical OPNet contract project looks like this:
76
+
77
+ ```
78
+ my-opnet-project/
79
+ ├── src/ # AssemblyScript source code
80
+ │ ├── token/ # Token contract
81
+ │ │ ├── MyToken.ts # Contract implementation
82
+ │ │ └── index.ts # Entry point with Blockchain.contract
83
+ │ ├── nft/ # NFT contract (optional)
84
+ │ │ ├── MyNFT.ts
85
+ │ │ └── index.ts
86
+ │ └── tsconfig.json # AssemblyScript config for src/
87
+ ├── build/ # Compiled output
88
+ │ ├── MyToken.wasm # Token contract build
89
+ │ └── MyNFT.wasm # NFT contract build
90
+ ├── tests/ # Test files
91
+ │ └── MyToken.spec.ts
92
+ ├── asconfig.json # AssemblyScript configuration
93
+ ├── package.json # Node.js configuration
94
+ └── tsconfig.json # TypeScript configuration
95
+ ```
96
+
97
+ ## Key Files
98
+
99
+ ### src/token/index.ts
100
+
101
+ The entry point for each contract that sets up the contract instance:
102
+
103
+ ```typescript
104
+ import { Blockchain } from '@btc-vision/btc-runtime/runtime';
105
+ import { revertOnError } from '@btc-vision/btc-runtime/runtime/abort/abort';
106
+ import { MyToken } from './MyToken';
107
+
108
+ // DO NOT TOUCH TO THIS.
109
+ Blockchain.contract = () => {
110
+ // ONLY CHANGE THE CONTRACT CLASS NAME.
111
+ // DO NOT ADD CUSTOM LOGIC HERE.
112
+
113
+ return new MyToken();
114
+ };
115
+
116
+ // VERY IMPORTANT
117
+ export * from '@btc-vision/btc-runtime/runtime/exports';
118
+
119
+ // VERY IMPORTANT
120
+ export function abort(message: string, fileName: string, line: u32, column: u32): void {
121
+ revertOnError(message, fileName, line, column);
122
+ }
123
+ ```
124
+
125
+ ### asconfig.json
126
+
127
+ AssemblyScript compiler configuration with per-contract targets:
128
+
129
+ ```json
130
+ {
131
+ "targets": {
132
+ "token": {
133
+ "outFile": "build/MyToken.wasm",
134
+ "use": ["abort=src/token/index/abort"]
135
+ },
136
+ "nft": {
137
+ "outFile": "build/MyNFT.wasm",
138
+ "use": ["abort=src/nft/index/abort"]
139
+ }
140
+ },
141
+ "options": {
142
+ "sourceMap": false,
143
+ "optimizeLevel": 3,
144
+ "shrinkLevel": 1,
145
+ "converge": true,
146
+ "noAssert": false,
147
+ "enable": [
148
+ "sign-extension",
149
+ "mutable-globals",
150
+ "nontrapping-f2i",
151
+ "bulk-memory",
152
+ "simd",
153
+ "reference-types",
154
+ "multi-value"
155
+ ],
156
+ "runtime": "stub",
157
+ "memoryBase": 0,
158
+ "initialMemory": 1,
159
+ "exportStart": "start",
160
+ "transform": "@btc-vision/opnet-transform"
161
+ }
162
+ }
163
+ ```
164
+
165
+ | Option | Description |
166
+ |--------|-------------|
167
+ | `targets` | Per-contract build targets with output paths |
168
+ | `use` | Links custom abort function for error handling |
169
+ | `optimizeLevel` | Optimization level (0-3), higher = faster but larger |
170
+ | `shrinkLevel` | Code size reduction (0-2) |
171
+ | `transform` | OPNet transform for decorator processing |
172
+ | `runtime: "stub"` | Minimal runtime (OPNet provides its own) |
173
+
174
+ ### package.json Scripts
175
+
176
+ Recommended scripts for your `package.json`:
177
+
178
+ ```json
179
+ {
180
+ "scripts": {
181
+ "build:token": "asc src/token/index.ts --target token --measure --uncheckedBehavior never",
182
+ "build:nft": "asc src/nft/index.ts --target nft --measure --uncheckedBehavior never"
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## btc-runtime Library Structure
188
+
189
+ ### Runtime Library Architecture
190
+
191
+ This diagram shows the internal organization of the @btc-vision/btc-runtime package:
192
+
193
+ ```mermaid
194
+ ---
195
+ config:
196
+ theme: dark
197
+ ---
198
+ graph LR
199
+ subgraph runtime["btc-runtime Package"]
200
+ RUNTIME["runtime/"]
201
+ INDEX["index.ts<br/>Main Exports"]
202
+ end
203
+
204
+ subgraph contracts["Contract Base Classes"]
205
+ OPNET["OP_NET.ts<br/>Base Contract"]
206
+ OP20["OP20.ts<br/>Fungible Token"]
207
+ OP721["OP721.ts<br/>NFT Standard"]
208
+ GUARD["ReentrancyGuard.ts<br/>Security"]
209
+ end
210
+
211
+ subgraph storage["Storage System"]
212
+ STORED["StoredU256.ts<br/>Persistent Values"]
213
+ STOREDSTR["StoredString.ts<br/>String Storage"]
214
+ STOREDMAP["StoredMapU256.ts<br/>Key-Value Maps"]
215
+ STOREDARRAY["StoredU256Array.ts<br/>Dynamic Arrays"]
216
+ end
217
+
218
+ subgraph memory["Memory Management"]
219
+ ADDRMAP["AddressMemoryMap.ts<br/>Address Mappings"]
220
+ MAPOFMAP["MapOfMap.ts<br/>Nested Maps"]
221
+ KEYMERGE["KeyMerger.ts<br/>Key Utilities"]
222
+ end
223
+
224
+ subgraph types["Types & Utilities"]
225
+ ADDR["Address.ts<br/>32-byte Addresses"]
226
+ CALLDATA["Calldata.ts<br/>Input Parsing"]
227
+ BYTESW["BytesWriter.ts<br/>Output Builder"]
228
+ BYTESR["BytesReader.ts<br/>Data Reader"]
229
+ SAFE["SafeMath.ts<br/>Overflow Protection"]
230
+ REV["Revert.ts<br/>Error Handling"]
231
+ end
232
+
233
+ subgraph blockchain["Blockchain Environment"]
234
+ BLOCKCHAIN["BlockchainEnvironment.ts<br/>Runtime Context"]
235
+ TX["Transaction.ts<br/>TX Data"]
236
+ BLOCK["Block.ts<br/>Block Info"]
237
+ end
238
+
239
+ subgraph events["Event System"]
240
+ EVENT["NetEvent.ts<br/>Event Base"]
241
+ TRANSFER["TransferredEvent.ts"]
242
+ APPROVAL["ApprovedEvent.ts"]
243
+ MINT["MintedEvent.ts"]
244
+ BURN["BurnedEvent.ts"]
245
+ end
246
+
247
+ RUNTIME --> INDEX
248
+
249
+ INDEX --> OPNET
250
+ INDEX --> OP20
251
+ INDEX --> OP721
252
+ INDEX --> GUARD
253
+
254
+ INDEX --> STORED
255
+ INDEX --> STOREDSTR
256
+ INDEX --> STOREDMAP
257
+ INDEX --> STOREDARRAY
258
+
259
+ INDEX --> ADDRMAP
260
+ INDEX --> MAPOFMAP
261
+
262
+ INDEX --> ADDR
263
+ INDEX --> CALLDATA
264
+ INDEX --> BYTESW
265
+ INDEX --> BYTESR
266
+ INDEX --> SAFE
267
+ INDEX --> REV
268
+
269
+ INDEX --> BLOCKCHAIN
270
+ INDEX --> EVENT
271
+
272
+ OPNET -.->|"uses"| BLOCKCHAIN
273
+ OPNET -.->|"uses"| EVENT
274
+ OP20 -.->|"extends"| GUARD
275
+ GUARD -.->|"extends"| OPNET
276
+
277
+ OP20 -.->|"uses"| STORED
278
+ OP20 -.->|"uses"| ADDRMAP
279
+ OP20 -.->|"uses"| SAFE
280
+
281
+ BLOCKCHAIN --> TX
282
+ BLOCKCHAIN --> BLOCK
283
+
284
+ EVENT --> TRANSFER
285
+ EVENT --> APPROVAL
286
+ EVENT --> MINT
287
+ EVENT --> BURN
288
+ ```
289
+
290
+ Understanding the btc-runtime structure helps you find the right imports:
291
+
292
+ ```
293
+ @btc-vision/btc-runtime/
294
+ ├── runtime/ # Main runtime directory
295
+ │ ├── index.ts # Main exports
296
+ │ ├── contracts/ # Contract base classes
297
+ │ │ ├── OP_NET.ts # Base contract class
298
+ │ │ ├── OP20.ts # Fungible token standard
299
+ │ │ ├── OP20S.ts # Token with signatures
300
+ │ │ ├── OP721.ts # NFT standard
301
+ │ │ └── ReentrancyGuard.ts # Reentrancy protection
302
+ │ ├── storage/ # Storage types
303
+ │ │ ├── StoredU256.ts
304
+ │ │ ├── StoredString.ts
305
+ │ │ ├── StoredArray.ts
306
+ │ │ ├── StoredMap.ts
307
+ │ │ └── ...
308
+ │ ├── math/ # Math utilities
309
+ │ │ ├── SafeMath.ts
310
+ │ │ └── SafeMathI128.ts
311
+ │ ├── types/ # Core types
312
+ │ │ ├── Address.ts
313
+ │ │ ├── Calldata.ts
314
+ │ │ ├── BytesWriter.ts
315
+ │ │ ├── BytesReader.ts
316
+ │ │ └── Selector.ts
317
+ │ ├── events/ # Event system
318
+ │ │ ├── NetEvent.ts
319
+ │ │ ├── predefined/
320
+ │ │ └── ...
321
+ │ ├── env/ # Blockchain environment
322
+ │ │ └── BlockchainEnvironment.ts
323
+ │ └── interfaces/ # TypeScript interfaces
324
+ ```
325
+
326
+ ## Import Patterns
327
+
328
+ ### Basic Imports
329
+
330
+ ```typescript
331
+ // Core runtime - contracts and utilities
332
+ import {
333
+ OP_NET,
334
+ OP20,
335
+ OP721,
336
+ Blockchain,
337
+ Address,
338
+ Calldata,
339
+ BytesWriter,
340
+ BytesReader,
341
+ SafeMath,
342
+ Revert,
343
+ } from '@btc-vision/btc-runtime/runtime';
344
+
345
+ // Big numbers
346
+ import { u128, u256 } from '@btc-vision/as-bignum/assembly';
347
+ ```
348
+
349
+ ### Storage Types
350
+
351
+ ```typescript
352
+ import {
353
+ StoredU256,
354
+ StoredString,
355
+ StoredBoolean,
356
+ StoredAddress,
357
+ StoredU256Array,
358
+ StoredAddressArray,
359
+ StoredMapU256,
360
+ AddressMemoryMap,
361
+ } from '@btc-vision/btc-runtime/runtime';
362
+ ```
363
+
364
+ ### Events
365
+
366
+ ```typescript
367
+ import {
368
+ NetEvent,
369
+ TransferEvent,
370
+ ApprovalEvent,
371
+ MintEvent,
372
+ BurnEvent,
373
+ } from '@btc-vision/btc-runtime/runtime';
374
+ ```
375
+
376
+ ### Contract Initialization
377
+
378
+ ```typescript
379
+ import {
380
+ OP20InitParameters,
381
+ OP721InitParameters,
382
+ } from '@btc-vision/btc-runtime/runtime';
383
+ ```
384
+
385
+ ### Storage Pointer System
386
+
387
+ This diagram illustrates how OPNet manages persistent storage using pointers:
388
+
389
+ ```mermaid
390
+ ---
391
+ config:
392
+ theme: dark
393
+ ---
394
+ flowchart LR
395
+ subgraph contract["Contract Storage Model"]
396
+ CONTRACT["MyToken Contract"]
397
+ end
398
+
399
+ subgraph pointers["Storage Pointers"]
400
+ P1["Pointer 0<br/>Total Supply"]
401
+ P2["Pointer 1<br/>Token Name"]
402
+ P3["Pointer 2<br/>Token Symbol"]
403
+ P4["Pointer 3<br/>Decimals"]
404
+ P5["Pointer 4<br/>Balance Map"]
405
+ P6["Pointer 5<br/>Allowance Map"]
406
+ end
407
+
408
+ subgraph state["Blockchain State"]
409
+ STATE[("Persistent Storage")]
410
+
411
+ subgraph values["Stored Values"]
412
+ V1["0x00...01<br/>1000000 tokens"]
413
+ V2["0x00...02<br/>MyToken"]
414
+ V3["0x00...03<br/>MTK"]
415
+ V4["0x00...04<br/>18"]
416
+ end
417
+
418
+ subgraph balances["Balance Mapping"]
419
+ B1["SHA256(pointer 4 + address1)<br/>→ 1000 tokens"]
420
+ B2["SHA256(pointer 4 + address2)<br/>→ 500 tokens"]
421
+ B3["SHA256(pointer 4 + address3)<br/>→ 250 tokens"]
422
+ end
423
+
424
+ subgraph allowances["Allowance Nested Map"]
425
+ A1["SHA256(pointer 5 + owner + spender)<br/>→ 100 tokens"]
426
+ end
427
+ end
428
+
429
+ CONTRACT --> P1
430
+ CONTRACT --> P2
431
+ CONTRACT --> P3
432
+ CONTRACT --> P4
433
+ CONTRACT --> P5
434
+ CONTRACT --> P6
435
+
436
+ P1 -.->|"reads/writes"| V1
437
+ P2 -.->|"reads/writes"| V2
438
+ P3 -.->|"reads/writes"| V3
439
+ P4 -.->|"reads/writes"| V4
440
+
441
+ P5 -.->|"with address key"| B1
442
+ P5 -.->|"with address key"| B2
443
+ P5 -.->|"with address key"| B3
444
+
445
+ P6 -.->|"with owner+spender"| A1
446
+
447
+ V1 --> STATE
448
+ V2 --> STATE
449
+ V3 --> STATE
450
+ V4 --> STATE
451
+ B1 --> STATE
452
+ B2 --> STATE
453
+ B3 --> STATE
454
+ A1 --> STATE
455
+ ```
456
+
457
+ ## Contract Organization
458
+
459
+ ### Single Contract Project
460
+
461
+ For simple projects with one contract:
462
+
463
+ ```
464
+ src/
465
+ ├── token/
466
+ │ ├── MyToken.ts
467
+ │ └── index.ts
468
+ └── tsconfig.json
469
+ ```
470
+
471
+ ### Multi-Contract Project
472
+
473
+ For larger projects with multiple contracts:
474
+
475
+ ```
476
+ src/
477
+ ├── token/
478
+ │ ├── MyToken.ts
479
+ │ └── index.ts
480
+ ├── stablecoin/
481
+ │ ├── MyStablecoin.ts
482
+ │ └── index.ts
483
+ ├── nft/
484
+ │ ├── MyNFT.ts
485
+ │ └── index.ts
486
+ ├── shared/
487
+ │ ├── CustomTypes.ts
488
+ │ └── Helpers.ts
489
+ └── tsconfig.json
490
+ ```
491
+
492
+ ### Shared Logic
493
+
494
+ For contracts sharing common functionality:
495
+
496
+ ```typescript
497
+ // src/shared/Pausable.ts
498
+ import { Blockchain, OP_NET, Revert, StoredBoolean } from '@btc-vision/btc-runtime/runtime';
499
+
500
+ const pausedPointer: u16 = Blockchain.nextPointer;
501
+
502
+ export abstract class Pausable extends OP_NET {
503
+ private _paused: StoredBoolean = new StoredBoolean(pausedPointer, false);
504
+
505
+ protected whenNotPaused(): void {
506
+ if (this._paused.value) {
507
+ throw new Revert('Contract is paused');
508
+ }
509
+ }
510
+
511
+ protected pause(): void {
512
+ this.onlyDeployer(Blockchain.tx.sender);
513
+ this._paused.value = true;
514
+ }
515
+
516
+ protected unpause(): void {
517
+ this.onlyDeployer(Blockchain.tx.sender);
518
+ this._paused.value = false;
519
+ }
520
+ }
521
+
522
+ // src/token/MyToken.ts
523
+ import { Pausable } from '../shared/Pausable';
524
+
525
+ export class MyToken extends Pausable {
526
+ // Now has pause functionality
527
+ }
528
+ ```
529
+
530
+ ## Comparison with Solidity Projects
531
+
532
+ | Solidity | OPNet | Notes |
533
+ |----------|-------|-------|
534
+ | `contracts/` | `src/token/`, `src/nft/` | Contract source files (one folder per contract) |
535
+ | `interfaces/` | `src/shared/` | Type definitions and shared logic |
536
+ | `libraries/` | `src/shared/` | Shared utilities |
537
+ | `test/` | `tests/` | Test files |
538
+ | `artifacts/` | `build/` | Compiled output |
539
+ | `hardhat.config.js` | `asconfig.json` | Build configuration |
540
+
541
+ ## Best Practices
542
+
543
+ ### 1. Organize by Feature
544
+
545
+ ```
546
+ src/
547
+ ├── token/ # Token contract
548
+ ├── stablecoin/ # Stablecoin contract
549
+ ├── nft/ # NFT contract
550
+ ├── governance/ # Governance contract
551
+ └── shared/ # Shared utilities and types
552
+ ```
553
+
554
+ ### 2. Use Consistent Naming
555
+
556
+ ```typescript
557
+ // Contract files: PascalCase.ts
558
+ MyToken.ts
559
+ MyStablecoin.ts
560
+
561
+ // Type files: PascalCase.ts
562
+ CustomTypes.ts
563
+
564
+ // Utility files: camelCase.ts
565
+ mathHelpers.ts
566
+ ```
567
+
568
+ ### 3. Entry Point Pattern
569
+
570
+ Each contract should have its own index.ts with the proper pattern:
571
+
572
+ ```typescript
573
+ // src/token/index.ts
574
+ import { Blockchain } from '@btc-vision/btc-runtime/runtime';
575
+ import { revertOnError } from '@btc-vision/btc-runtime/runtime/abort/abort';
576
+ import { MyToken } from './MyToken';
577
+
578
+ Blockchain.contract = () => {
579
+ return new MyToken();
580
+ };
581
+
582
+ export * from '@btc-vision/btc-runtime/runtime/exports';
583
+
584
+ export function abort(message: string, fileName: string, line: u32, column: u32): void {
585
+ revertOnError(message, fileName, line, column);
586
+ }
587
+ ```
588
+
589
+ ### 4. Separate Concerns
590
+
591
+ ```typescript
592
+ // Good: Each contract has a single responsibility
593
+ export class TokenContract extends OP20 { /* token logic */ }
594
+ export class GovernanceContract extends OP_NET { /* governance logic */ }
595
+
596
+ // Bad: One contract doing too much
597
+ export class EverythingContract extends OP_NET {
598
+ // token logic
599
+ // governance logic
600
+ // oracle logic
601
+ // etc.
602
+ }
603
+ ```
604
+
605
+ ## Testing Structure
606
+
607
+ ```
608
+ tests/
609
+ ├── unit/ # Unit tests
610
+ │ ├── MyToken.spec.ts
611
+ │ └── SafeMath.spec.ts
612
+ ├── integration/ # Integration tests
613
+ │ └── TokenTransfer.spec.ts
614
+ └── fixtures/ # Test fixtures
615
+ └── testData.ts
616
+ ```
617
+
618
+ ## Next Steps
619
+
620
+ Now that you understand the project structure:
621
+
622
+ 1. [Learn about the blockchain environment](../core-concepts/blockchain-environment.md)
623
+ 2. [Understand the storage system](../core-concepts/storage-system.md)
624
+ 3. [See complete examples](../examples/basic-token.md)
625
+
626
+ ---
627
+
628
+ **Navigation:**
629
+ - Previous: [First Contract](./first-contract.md)
630
+ - Next: [Blockchain Environment](../core-concepts/blockchain-environment.md)