Repository: disintar/toncli (language: python)

Issue:
Version: 0.0.22
- [x] Add `sendboc` command, so if `.boc` file pass - will send it via lite-cliente, if `.fif` file pass - will
  invoke `tncli fift sendboc` so fift script will be run, and then boc file on output will be sended
- [x] Add `--data-params` to build command, to auto-generate data cells 
- [x] Update `stdlib.fc` to support nft
- [x] Critical fix: `self.wait_for_deploy(contracts=real_contracts)` instead of `self.wait_for_deploy(contracts=contracts)`
- [x] Add `.gitignore` to protect contract keys leaks
- [x] Add cell slice parser in lite-client
- [x] Add parse address to `TonUtils.fif`
- [x] Fix custom path to `fift` / `func` / `lite-client` on startup
- [x] Add command wallet to check wallets addresses 
- [x] Force `fift` / `func` libs update
- [x] More stability in lite-client interaction
- [x] Send `exteranal_message` to contract without need to provide wrapper of `external_message`, just pass body bytes (
  with support of multiple contracts)
- [x] Send `internal_message` from deploy wallet in one command
- [x] NFT Example deploy
- [x] Add retry parameter to `lite-client`, try several times to do query
- [x] Add windows support
- [x] Func tests
- [x] Custom `stdlib-tests.fc` and `asm-tests.fif` for tests
- [x] Documentation update
Add windows support



Discussion / hints:

Fix patch:
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..81229e8
Binary files /dev/null and b/.DS_Store differ
diff --git a/INSTALLATION.md b/INSTALLATION.md
new file mode 100644
index 0000000..e8339ae
--- /dev/null
+++ b/INSTALLATION.md
@@ -0,0 +1,63 @@
+
+
+
+## Installation from pre-build
+
+### Linux / macOS (intel)
+
+1. Download needed prebuild for your system from [here](https://github.com/newton-blockchain/ton/actions?query=branch%3Amaster+is%3Acompleted)
+2. Install `Python3.9` or higher
+3. Run `pip install toncli` or `pip3 install toncli`
+   1. If you see `WARNING: The script toncli is installed in '/bla/bla/bla/Python/3.9/bin' which is not on PATH.` please manually add absolute `bin` path to PATH env
+4. Run `toncli` and pass absolute path to `func` / `fift` / `lite-client` from first step
+
+### Windows
+
+1. You need to download the latest version of python (3.9+) from the official website, you can do this [here](https://www.python.org/downloads/)
+   1. Please, **don't** install Microsoft Store version. It will not work.
+2. During installation, on the first screen, you need to click the "Add Python to PATH" checkbox, this is very important!
+
+![image](https://user-images.githubusercontent.com/19264196/160259049-8ed99862-a765-4653-84cb-b6818c0aa0b3.png)
+
+3. After successful installation, open the console (you can do this by pressing `Win+X`, selecting `Windows Terminal` in the menu)
+
+4. Install `toncli` by running `pip install toncli`
+
+5. Download the compiled TON binaries from [here](https://github.com/newton-blockchain/ton/actions/runs/1713804021) (you need to be logged in to GitHub)
+
+![image](https://user-images.githubusercontent.com/19264196/160259203-07fd0e26-9b8e-4aff-b4f0-8e4e6f871088.png)
+
+6. Unzip the downloaded archive 
+
+7. Add [libcrypto-1_1-x64.dll](https://disk.yandex.ru/d/BJk7WPwr_JT0fw) to unziped files
+
+![image](https://user-images.githubusercontent.com/19264196/160259288-3af468d7-74ac-45cb-9001-9f2604cf4119.png)
+
+9. Open the folder in the console (right mouse button, open in the terminal in Windows 11, Windows 10 and less - copy the path in Explorer and in the PowerShell (win+x) and run `cd <<copied path>>`)
+
+10. Run `toncli` in console, it will automatically detect `.exe` files and added paths to config:
+
+![image](https://user-images.githubusercontent.com/19264196/160259355-dacc0234-f8b7-4b9e-b1cd-8a5d6df0712a.png)
+
+11. Success! 
+
+P.S. for a beautiful display of colors and emoticons, it is advised to install the latest version of the 'Windows Terminal Preview' from the Microsoft Store
+
+
+## Installation from source
+
+### macOS (m1)
+
+1. Please follow [this](/docs/apple_m1_compile_fix.md) guide to compile `func` / `fift`/ `lite-client`
+2. Run `pip install toncli` or `pip3 install toncli`
+   1. If you see `WARNING: The script toncli is installed in '/bla/bla/bla/Python/3.9/bin' which is not on PATH.` please manually add absolute `bin` path to PATH env
+3. Run `toncli` and pass absolute path to `func` / `fift` / `lite-client` from first step
+
+### Linux
+
+1. Follow official [docs](https://ton.org/docs/#/compile) to compile sources
+2. Run `pip install toncli` or `pip3 install toncli`
+   1. If you see `WARNING: The script toncli is installed in '/bla/bla/bla/Python/3.9/bin' which is not on PATH.` please manually add absolute `bin` path to PATH env
+3. Run `toncli` and pass absolute path to `func` / `fift` / `lite-client` from first step
+
+
diff --git a/README.md b/README.md
index 32c50f2..186e366 100644
--- a/README.md
+++ b/README.md
@@ -15,11 +15,13 @@
 [![Codacy Badge](https://app.codacy.com/project/badge/Grade/8f4acbbba3a743f992062c377c48c675)](https://www.codacy.com/gh/disintar/toncli/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=disintar/toncli&amp;utm_campaign=Badge_Grade)
 [![TON](https://img.shields.io/badge/%F0%9F%92%8E-TON-green)](https://ton.org)
 
-TON smart contract command line interface
+The Open Network cross-platform smart contract command line interface. 
 
-## State
+Easy to deploy and interact with TON smart contracts.
 
-Working!
+## Installation
+
+Toncli support Windows / macOS (m1 / intel) / Linux, installation guid can be found: [INSTALLATION.md](/INSTALLATION.md)
 
 ### Usage and docs
 New to `toncli`?
@@ -41,25 +43,26 @@ There is many TODOs in code - feel free to fix them and create PRs
 ## Features and status
 
 | Feature                                                                                         | Status |
-|-------------------------------------------------------------------------------------------------|--------|
-| `fift` / `func` / `lite-server` usage                                                           | ✅      |
-| Easy bootstrap project samples `wallet`                                                         | ✅      |
-| Deploy-wallet for auto send TON to contracts and tests                                          | ✅      |
-| Compile func to `build/` from `func/` with `files.yaml`                                         | ✅      |
-| Auto send TON to init contract address                                                          | ✅      |
-| Deploy to mainnet / testnet                                                                     | ✅      |
-| Project interact after deploy: easily send messages, run getmethods                             | ✅      |
-| Load from hard project structure (example: `src/projects/wallet`)                               | ✅      |
-| Run remote contracts locally (get cells from chain and run locally to get error / debug / etc.) | ✅      |
-| Get contract address by `toncli address`                                                         | ❌      |
-| Gas auto calculation for store & deploy                                                         | ❌      |
-| Add more project samples with advanced usage                                                    | ❌      |
-| Project tests with `runvmcode`                                                                  | ❌      |
-| Project debug                                                                                   | ❌      |
-| Library support                                                                                 | ❌      |
-| Init Message support  (with signature)                                                          | ❌      |
-| Docs for contract creation for beginners                                                        | ❌      |
-| Advanced user-friendly docs on `fift`, `func`                                                   | ❌      |
+|-------------------------------------------------------------------------------------------------|-----|
+| `fift` / `func` / `lite-server` usage                                                           | ✅   |
+| Easy bootstrap project samples `wallet`                                                         | ✅   |
+| Deploy-wallet for auto send TON to contracts and tests                                          | ✅   |
+| Compile func to `build/` from `func/` with `files.yaml`                                         | ✅   |
+| Auto send TON to init contract address                                                          | ✅   |
+| Deploy to mainnet / testnet                                                                     | ✅   |
+| Project interact after deploy: easily send messages, run getmethods                             | ✅   |
+| Load from hard project structure (example: `src/projects/wallet`)                               | ✅   |
+| Run remote contracts locally (get cells from chain and run locally to get error / debug / etc.) | ✅   |
+| Get contract address by `toncli address`                                                        | ✅    |
+| Docs for contract creation for beginners                                                        | ✅    |
+| Project tests with `runvmcode`                                                                  | ✅    |
+| Windows & Linux support                                                                         | ✅    |
+| Gas auto calculation for store & deploy                                                         | ❌   |
+| Add more project samples with advanced usage                                                    | ❌   |
+| Project debug                                                                                   | ❌   |
+| Library support                                                                                 | ❌   |
+| Init Message support  (with signature)                                                          | ❌   |
+| Advanced user-friendly docs on `fift`, `func`                                                   | ❌   |
 
 ## Commands
 
@@ -97,3 +100,13 @@ git clone git@github.com:disintar/toncli.git
 cd toncli && pip install -e .
 ```
 
+## Version migration
+
+#### 0.20
+
+The easy migration method - remove `fift-libs`, `func-libs` from `~/.config/toncli` or delete whole directory `~/.config/toncli`
+
+
+## Help and questions
+
+Feel free to ask questions and help in official telegram chats: [Russion](https://t.me/tondev) / [English](https://t.me/tondev_eng)
\ No newline at end of file
diff --git a/docs/advanced/commands.md b/docs/advanced/commands.md
index b9c3915..5ff9e3c 100644
--- a/docs/advanced/commands.md
+++ b/docs/advanced/commands.md
@@ -8,6 +8,7 @@
 | `toncli get [--contract NAME] [GET_METHOD] [--fift FIFT]`                                                                                      | Run get method on contract   if fift provided - will run fift script on get output (all data will passed to stack)                                                                                                                                                                  |
 | `toncli run_transaction [-h] [--net {testnet,mainnet}] logical_time transaction_hash smc_address`                                              | Debug message by logical time, transaction hash, account address. Get account data / code / balance and run transaction locally                                                                                                                                                     |
 | `toncli tointeger`                                                                                                                             | Parse string to integer to pass it to func code                                                                                                                                                                                                                                     |
+| `toncli addrs`                                                                                                                                 | Get smart-contracts addresses of current project                                                                                                                                                                                                                                    |
 |                                                                                                                                                |                                                                                                                                                                                                                                                                                     |
 | `toncli fift [-h] [--net {testnet,mainnet}] [--workchain WORKCHAIN] [--update] [--fift-args FIFT_ARGS]  [--lite-client-args LITE_CLIENT_ARGS]` |                                                                                                                                                                                                                                                                                     |
 | `toncli fift run [--build] [files] [command lite arguments to files]`                                                                          | Run fift file, if --build passed - func code in project will be build first                                                                                                                                                                                                         |
diff --git a/docs/advanced/intresting_features.md b/docs/advanced/intresting_features.md
index e7c659d..23b33dd 100644
--- a/docs/advanced/intresting_features.md
+++ b/docs/advanced/intresting_features.md
@@ -3,9 +3,10 @@
 0. All commands have well described `help` messages you can run any command with `-h` flag to see help
    1. `toncli -h` - as example
 1. You can use `toncli f` / `toncli fift` instead of running `fift -I .../fift-libs`
-2. You can use `toncli fc` / `toncli func` instead of running `func -SPA .../func-libs/stdlib.fc `
+2. You can use `toncli fc` / `toncli func` instead of running `func -SPA .../func-libs/stdlib.func `
 3. You can use `toncli lc` / `toncli lite-client` instead of running `lite-client -C /usr/lib/testnet-global.config.json`
    1. Network configuration `--net` flag, you may want to see help message
 4. You can convert string to integer `toncli tointeger TEST` to add text to your `func` files
 5. You can auto build func files and then run own fift file E.g. `toncli run fift/load_c4.fif --build` in `external_data`
-6. You can build all contracts in project by `toncli fc build`
\ No newline at end of file
+6. You can build all contracts in project by `toncli fc build`
+7. You can pass data to stack of data.fif in your project (path is in `project.yaml`) by passing it in parameter `data-params` of `deploy` command. For example, `toncli deploy --data-params==hello_world`
\ No newline at end of file
diff --git a/docs/advanced/libs_configuration.md b/docs/advanced/libs_configuration.md
new file mode 100644
index 0000000..6b57583
--- /dev/null
+++ b/docs/advanced/libs_configuration.md
@@ -0,0 +1,8 @@
+# FIFT AND FUNC LIBS CONFIGURATION
+We decided to not update your local copies ot these libs automatically because you can change them according to your needs. But if we update these libs we will notify you with warning:
+```
+Its seems that your local fift and func libs differs from their actual versions.
+```
+You will have 2 options to remove this warning:
+1. Update your local copies of libs with command `toncli update_libs`
+2. Remove the warning by adding additional parameter (or changing existing parameter) `LIBS_WARNING=False`
\ No newline at end of file
diff --git a/docs/advanced/multiple_contracts.md b/docs/advanced/multiple_contracts.md
index 65c937e..78b390f 100644
--- a/docs/advanced/multiple_contracts.md
+++ b/docs/advanced/multiple_contracts.md
@@ -17,12 +17,12 @@ Add `test` smart contract to file, so it'll look like this:
 contract:
   data: fift/data.fif
   func:
-    - func/code.fc
+    - func/code.func
 
 test:
   data: fift/test.fif
   func:
-    - func/code.fc
+    - func/code.func
 ```
 
 About project structure you can read in `advanced/project_structure.md`.
@@ -80,4 +80,5 @@ INFO: 🦘 Found existing deploy-wallet [kQDl5ZpiwlFCb4Bj4sKIvU15rh9Bq2MmCQmw5Fr
 INFO: 👯 [test] [kQCuGN4Varstnk0serOGa2yhBG39sY7ToG8xsxK3FhEAPAeE] runmethod ['seqno']
 INFO: 🧐 Output: [ 0  ]
 ERROR: 🧐 Can't auto parse strin
-```
\ No newline at end of file
+```
+
diff --git a/docs/advanced/project_structure.md b/docs/advanced/project_structure.md
index 2b1fa4a..878a22c 100644
--- a/docs/advanced/project_structure.md
+++ b/docs/advanced/project_structure.md
@@ -7,7 +7,7 @@
 ├── fift
 │   ├── data.fif # data cell
 ├── func
-│   ├── code.fc # main func code
+│   ├── code.func # main func code
 ├── tests # all tests on smart contract goes here
 └── project.yaml # project structure description
 ```
@@ -20,7 +20,7 @@ contract:
   lib: fift/lib.fif (if needed)
   message: fift/message.fif (if needed)
   func:
-    - func/code.fc
+    - func/code.func
     - ...
 
 contract2:
@@ -28,7 +28,7 @@ contract2:
   lib: fift/contract2_lib.fif (if needed)
   message: fift/contract2_message.fif (if needed)
   func:
-    - func/code.fc
+    - func/code.func
     - ...
 
 ...
diff --git a/pyproject.toml b/pyproject.toml
index ff3e2bb..ccb057a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,6 +6,7 @@ requires = [
     "appdirs",
     "requests",
     "pyyaml",
-    "Jinja2"
+    "Jinja2",
+    "bitstring"
 ]
 build-backend = "setuptools.build_meta"
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 88cb94a..9454d6f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,4 +2,5 @@ colorama
 appdirs
 requests
 pyyaml
-Jinja2
\ No newline at end of file
+Jinja2
+bitstring
\ No newline at end of file
diff --git a/setup.py b/setup.py
index f1da324..2235de6 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@
 
 setuptools.setup(
     name="toncli",
-    version="0.0.17",
+    version="0.0.22",
     author="Andrey Tvorozhkov",
     author_email="andrey@head-labs.com",
     description="Easy to use CLI for fift / func projects",
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 0000000..909803f
Binary files /dev/null and b/src/.DS_Store differ
diff --git a/src/toncli/config.ini b/src/toncli/config.ini
index f9d7164..fbbe90b 100644
--- a/src/toncli/config.ini
+++ b/src/toncli/config.ini
@@ -2,4 +2,5 @@
 testnet = https://newton-blockchain.github.io/testnet-global.config.json
 mainnet = https://newton-blockchain.github.io/global.config.json
 toncenter_mainnet = https://toncenter.com/api/v2
-toncenter_testnet = https://testnet.toncenter.com/api/v2
\ No newline at end of file
+toncenter_testnet = https://testnet.toncenter.com/api/v2
+LIBS_WARNING = False
\ No newline at end of file
diff --git a/src/toncli/lib/fift-libs/AsmTests.fif b/src/toncli/lib/fift-libs/AsmTests.fif
new file mode 100644
index 0000000..c90c66d
--- /dev/null
+++ b/src/toncli/lib/fift-libs/AsmTests.fif
@@ -0,0 +1,1303 @@
+library TVM_Asm
+// simple TVM Assembler
+variable @atend
+{ "not in asm context" abort } @atend !
+{ `normal eq? not abort"must be terminated by }>" } : @normal?
+{ @atend @ 1 { @atend ! @normal? } does @atend ! } : @pushatend
+{ @pushatend <b } : <{
+{ @atend @ execute } : @endblk
+{ `normal @endblk } : }>
+{ }> b> } : }>c
+{ }>c <s } : }>s
+{ @atend @ 2 { @atend ! rot b> ref, swap @endblk } does @atend ! <b } : @|
+{ @atend @ 3 { @atend ! 2swap rot execute } does @atend ! <b } : @doafter<{
+{ over brembits <= } : @havebits
+{ rot + -rot + swap } : pair+
+{ rot >= -rot <= and } : 2x<=
+{ 2 pick brembitrefs 1- 2x<= } : @havebitrefs
+{ @havebits ' @| ifnot } : @ensurebits
+{ @havebitrefs ' @| ifnot } : @ensurebitrefs
+{ rot over @ensurebits -rot u, } : @simpleuop
+{ tuck sbitrefs @ensurebitrefs swap s, } : @addop
+{ tuck bbitrefs @ensurebitrefs swap b+ } : @addopb
+' @addopb : @inline
+{ 1 ' @addop does create } : @Defop
+{ 1 { <b swap s, swap 8 u, @addopb } does create } : @Defop(8u)
+{ 1 { <b swap s, swap 8 i, @addopb } does create } : @Defop(8i)
+{ 1 { <b swap s, swap 1- 8 u, @addopb } does create } : @Defop(8u+1)
+{ 1 { <b swap s, swap 4 u, @addopb } does create } : @Defop(4u)
+{ 1 { <b swap s, rot 4 u, swap 4 u, @addopb } does create } : @Defop(4u,4u)
+{ 1 { <b swap s, swap ref, @addopb } does create } : @Defop(ref)
+{ 1 { <b swap s, rot ref, swap ref, @addopb } does create } : @Defop(ref*2)
+{ <b 0xef 8 u, swap 12 i, b> } : si()
+// x mi ma -- ?
+{ rot tuck >= -rot <= and } : @range
+{ rot tuck < -rot > or } : @-range
+{ @-range abort"Out of range" } : @rangechk
+{ dup 0 < over 255 > or abort"Invalid stack register number" si() } : s()
+{ si() constant } : @Sreg
+-2 @Sreg s(-2)
+-1 @Sreg s(-1)
+0 @Sreg s0
+1 @Sreg s1
+2 @Sreg s2
+3 @Sreg s3
+4 @Sreg s4
+5 @Sreg s5
+6 @Sreg s6
+7 @Sreg s7
+8 @Sreg s8
+9 @Sreg s9
+10 @Sreg s10
+11 @Sreg s11
+12 @Sreg s12
+13 @Sreg s13
+14 @Sreg s14
+15 @Sreg s15
+{ dup 0 < over 7 > or abort"Invalid control register number" <b 0xcc 8 u, swap 4 u, b> } : c()
+{ c() constant } : @Creg
+0 @Creg c0
+1 @Creg c1
+2 @Creg c2
+3 @Creg c3
+4 @Creg c4
+5 @Creg c5
+7 @Creg c7
+{ <s 8 u@+ swap 0xef <> abort"not a stack register" 12 i@+ s> } : @bigsridx
+{ @bigsridx dup 16 >= over 0< or abort"stack register s0..s15 expected" } : @sridx
+{ rot @bigsridx tuck < -rot tuck > rot or abort"stack register out of range" } : @sridxrange
+{ swap @bigsridx + dup 16 >= over 0< or abort"stack register out of range" } : @sridx+
+{ <s 8 u@+ 4 u@+ s> swap 0xcc <> over 7 > or over 6 = or abort"not a control register c0..c5 or c7" } : @cridx
+{ <s 8 u@ 0xcc = } : @iscr?
+{ <b swap s, 1 { swap @sridx 4 u, @addopb } does create } : @Defop(s)
+{ <b swap s, 1 { rot @sridx 4 u, swap @sridx 4 u, @addopb } does create } : @Defop(s,s)
+{ <b swap s, 1 { swap @cridx 4 u, @addopb } does create } : @Defop(c)
+//
+// stack manipulation primitives
+// (simple stack primitives)
+//
+x{00} @Defop NOP
+x{01} @Defop SWAP
+x{0} @Defop(s) XCHG0
+{ @bigsridx swap @bigsridx 2dup =
+  { 2drop <b }
+  { 2dup < { swap } if dup 0=
+    { drop dup 16 <
+      { <b x{0} s, swap 4 u, }
+      { <b x{11} s, swap 8 u, }
+      cond
+    }
+    { over 16 >=
+      { tuck 16 >=
+        { <b x{11} s, 2 pick 8 u, x{11} s, swap 8 u, x{11} s, swap 8 u, }
+	{ <b x{0} s, 2 pick 4 u, x{11} s, swap 8 u, x{0} s, swap 4 u, } cond
+      }
+      { dup 1 =
+        { drop <b x{1} s, swap 4 u, }
+        { <b x{10} s, swap 4 u, swap 4 u, }
+        cond
+      } cond
+    } cond
+  } cond
+  @addopb } : XCHG
+x{ED4} @Defop(c) PUSHCTR
+x{ED5} @Defop(c) POPCTR
+{ dup @iscr?
+  ' PUSHCTR
+  { @bigsridx dup 16 <
+    { <b x{2} s, swap 4 u, }
+    { <b x{56} s, swap 8 u,
+    } cond
+  @addopb
+  } cond
+} : PUSH
+x{20} @Defop DUP
+x{21} @Defop OVER
+{ dup @iscr?
+  ' POPCTR
+  { @bigsridx dup 16 <
+    { <b x{3} s, swap 4 u, }
+    { <b x{57} s, swap 8 u,
+    } cond
+  @addopb
+  } cond
+} : POP
+x{30} @Defop DROP
+x{31} @Defop NIP
+
+// compound stack primitives
+{ @sridx rot @sridx rot @sridx swap <b x{4} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : XCHG3
+x{50} @Defop(s,s) XCHG2
+x{51} @Defop(s,s) XCPU
+{ <b x{52} s, rot @sridx 4 u, swap 1 @sridx+ 4 u, @addopb } : PUXC
+x{53} @Defop(s,s) PUSH2
+{ @sridx rot @sridx rot @sridx swap <b x{540} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : XCHG3_l
+{ @sridx rot @sridx rot @sridx swap <b x{541} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : XC2PU
+{ 1 @sridx+ rot @sridx rot @sridx swap <b x{542} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : XCPUXC
+{ @sridx rot @sridx rot @sridx swap <b x{543} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : XCPU2
+{ 1 @sridx+ rot @sridx rot 1 @sridx+ swap <b x{544} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : PUXC2
+{ 1 @sridx+ rot @sridx rot 1 @sridx+ swap <b x{545} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : PUXCPU
+{ 2 @sridx+ rot @sridx rot 1 @sridx+ swap <b x{546} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : PU2XC
+{ @sridx rot @sridx rot @sridx swap <b x{547} s, swap 4 u, swap 4 u, swap 4 u, @addopb } : PUSH3
+{ <b x{55} s, rot 1- 4 u, swap 1- 4 u, @addopb } : BLKSWAP
+{ dup { 1 swap BLKSWAP } { drop } cond } : ROLL
+{ dup { 1 BLKSWAP } { drop } cond } dup : -ROLL : ROLLREV
+x{5513} dup @Defop 2ROT @Defop ROT2
+
+// exotic stack primitives
+x{58} @Defop ROT
+x{59} dup @Defop -ROT @Defop ROTREV
+x{5A} dup @Defop 2SWAP @Defop SWAP2
+x{5B} dup @Defop 2DROP @Defop DROP2
+x{5C} dup @Defop 2DUP @Defop DUP2
+x{5D} dup @Defop 2OVER @Defop OVER2
+{ <b x{5E} s, rot 2 - 4 u, swap 4 u, @addopb } : REVERSE
+{ <b x{5F0} s, swap 4 u, @addopb } : BLKDROP
+{ over 0= abort"first argument must be non-zero"
+  <b x{5F} s, rot 4 u, swap 4 u, @addopb } : BLKPUSH
+x{60} dup @Defop PICK @Defop PUSHX
+x{61} @Defop ROLLX
+x{62} dup @Defop -ROLLX @Defop ROLLREVX
+x{63} @Defop BLKSWX
+x{64} @Defop REVX
+x{65} @Defop DROPX
+x{66} @Defop TUCK
+x{67} @Defop XCHGX
+x{68} @Defop DEPTH
+x{69} @Defop CHKDEPTH
+x{6A} @Defop ONLYTOPX
+x{6B} @Defop ONLYX
+{ over 0= abort"first argument must be non-zero"
+  <b x{6C} s, rot 4 u, swap 4 u, @addopb } : BLKDROP2
+
+// null primitives
+x{6D} dup @Defop NULL @Defop PUSHNULL
+x{6E} @Defop ISNULL
+// tuple primitives
+x{6F0} @Defop(4u) TUPLE
+x{6F00} @Defop NIL
+x{6F01} @Defop SINGLE
+x{6F02} dup @Defop PAIR @Defop CONS
+x{6F03} @Defop TRIPLE
+x{6F1} @Defop(4u) INDEX
+x{6F10} dup @Defop FIRST @Defop CAR
+x{6F11} dup @Defop SECOND @Defop CDR
+x{6F12} @Defop THIRD
+x{6F2} @Defop(4u) UNTUPLE
+x{6F21} @Defop UNSINGLE
+x{6F22} dup @Defop UNPAIR @Defop UNCONS
+x{6F23} @Defop UNTRIPLE
+x{6F3} @Defop(4u) UNPACKFIRST
+x{6F30} @Defop CHKTUPLE
+x{6F4} @Defop(4u) EXPLODE
+x{6F5} @Defop(4u) SETINDEX
+x{6F50} @Defop SETFIRST
+x{6F51} @Defop SETSECOND
+x{6F52} @Defop SETTHIRD
+x{6F6} @Defop(4u) INDEXQ
+x{6F60} dup @Defop FIRSTQ @Defop CARQ
+x{6F61} dup @Defop SECONDQ @Defop CDRQ
+x{6F62} @Defop THIRDQ
+x{6F7} @Defop(4u) SETINDEXQ
+x{6F70} @Defop SETFIRSTQ
+x{6F71} @Defop SETSECONDQ
+x{6F72} @Defop SETTHIRDQ
+x{6F80} @Defop TUPLEVAR
+x{6F81} @Defop INDEXVAR
+x{6F82} @Defop UNTUPLEVAR
+x{6F83} @Defop UNPACKFIRSTVAR
+x{6F84} @Defop EXPLODEVAR
+x{6F85} @Defop SETINDEXVAR
+x{6F86} @Defop INDEXVARQ
+x{6F87} @Defop SETINDEXVARQ
+x{6F88} @Defop TLEN
+x{6F89} @Defop QTLEN
+x{6F8A} @Defop ISTUPLE
+x{6F8B} @Defop LAST
+x{6F8C} dup @Defop TPUSH @Defop COMMA
+x{6F8D} @Defop TPOP
+x{6FA0} @Defop NULLSWAPIF
+x{6FA1} @Defop NULLSWAPIFNOT
+x{6FA2} @Defop NULLROTRIF
+x{6FA3} @Defop NULLROTRIFNOT
+x{6FA4} @Defop NULLSWAPIF2
+x{6FA5} @Defop NULLSWAPIFNOT2
+x{6FA6} @Defop NULLROTRIF2
+x{6FA7} @Defop NULLROTRIFNOT2
+{ <b x{6FB} s, rot 2 u, swap 2 u, @addopb } : INDEX2
+x{6FB4} @Defop CADR
+x{6FB5} @Defop CDDR
+{ <b x{6FE_} s, 3 roll 2 u, rot 2 u, swap 2 u, @addopb } : INDEX3
+x{6FD4} @Defop CADDR
+x{6FD5} @Defop CDDDR
+
+// integer constants
+x{70} dup @Defop ZERO @Defop FALSE
+x{71} @Defop ONE
+x{72} @Defop TWO
+x{7A} @Defop TEN
+x{7F} @Defop TRUE
+{ dup 10 <= over -5 >= and
+  { 15 and <b x{7} s, swap 4 u, }
+  { dup 8 fits
+    { <b x{80} s, swap 8 i, }
+    { dup 16 fits
+      { <b x{81} s, swap 16 i, }
+      { 11 { dup 259 > abort"integer too large" 8 + 2dup fits } until
+        <b x{82} s, over 3 >> 2- 5 u, -rot i,
+      } cond
+    } cond
+  } cond
+  @addopb } dup : PUSHINT : INT
+{ <b x{83} s, swap 1- 8 u, @addopb } : PUSHPOW2
+x{83FF} @Defop PUSHNAN
+{ <b x{84} s, swap 1- 8 u, @addopb } : PUSHPOW2DEC
+{ <b x{85} s, swap 1- 8 u, @addopb } : PUSHNEGPOW2
+//
+// other constants
+x{88} @Defop(ref) PUSHREF
+x{89} @Defop(ref) PUSHREFSLICE
+x{8A} @Defop(ref) PUSHREFCONT
+{ 1- dup 0< over 8 >= or abort"invalid slice padding"
+  swap 1 1 u, 0 rot u, } : @scomplete
+{ tuck sbitrefs swap 17 + swap @havebitrefs not
+  { <b rot s, b> PUSHREFSLICE }
+  { over sbitrefs 2dup 123 0 2x<=
+    { drop tuck 4 + 3 >> swap x{8B} s, over 4 u, 3 roll s,
+      -rot 3 << 4 + swap - @scomplete }
+    { 2dup 1 >= swap 248 <= and
+      { rot x{8C} s, swap 1- 2 u, over 7 + 3 >> tuck 5 u, 3 roll s,
+        -rot 3 << 1 + swap - @scomplete }
+      { rot x{8D} s, swap 3 u, over 2 + 3 >> tuck 7 u, 3 roll s,
+        -rot 3 << 6 + swap - @scomplete
+      } cond
+    } cond
+  } cond
+} dup : PUSHSLICE : SLICE
+// ( b' -- ? )
+{ bbitrefs or 0= } : @cont-empty?
+{ bbits 7 and 0= } : @cont-aligned?
+// ( b b' -- ? )
+{ bbitrefs over 7 and { 2drop drop false } {
+  swap 16 + swap @havebitrefs nip
+  } cond
+} : @cont-fits?
+// ( b b' -- ? )
+{ bbitrefs over 7 and { 2drop drop false } {
+  32 1 pair+ @havebitrefs nip
+  } cond
+} : @cont-ref-fit?
+// ( b b' b'' -- ? )
+{ over @cont-aligned? over @cont-aligned? and not { 2drop drop false } {
+  bbitrefs rot bbitrefs pair+ swap 32 + swap @havebitrefs nip
+  } cond
+} : @two-cont-fit?
+{ 2dup @cont-fits? not
+  { b> PUSHREFCONT }
+  { swap over bbitrefs 2dup 120 0 2x<=
+    { drop swap x{9} s, swap 3 >> 4 u, swap b+ }
+    { rot x{8F_} s, swap 2 u, swap 3 >> 7 u, swap b+ } cond
+  } cond
+} dup : PUSHCONT : CONT
+{ }> PUSHCONT } : }>CONT
+{ { @normal? PUSHCONT } @doafter<{ } : CONT:<{
+
+// arithmetic operations
+{ 2 { rot dup 8 fits
+      { nip <b rot s, swap 8 i, }
+      { rot drop <b swap PUSHINT swap s, }
+      cond @addopb
+    } does create
+} : @Defop(8i,alt)
+x{A0} @Defop ADD
+x{A1} @Defop SUB
+x{A2} @Defop SUBR
+x{A3} @Defop NEGATE
+x{A4} @Defop INC
+x{A5} @Defop DEC
+x{A6} x{A0} @Defop(8i,alt) ADDCONST
+{ negate ADDCONST } : SUBCONST
+x{A7} x{A8} @Defop(8i,alt) MULCONST
+' ADDCONST : ADDINT
+' SUBCONST : SUBINT
+' MULCONST : MULINT
+x{A8} @Defop MUL
+x{A904} @Defop DIV
+x{A905} @Defop DIVR
+x{A906} @Defop DIVC
+x{A908} @Defop MOD
+x{A90C} @Defop DIVMOD
+x{A90D} @Defop DIVMODR
+x{A90E} @Defop DIVMODC
+x{A925} @Defop RSHIFTR
+x{A926} @Defop RSHIFTC
+x{A935} @Defop(8u+1) RSHIFTR#
+x{A936} @Defop(8u+1) RSHIFTC#
+x{A938} @Defop(8u+1) MODPOW2#
+x{A984} @Defop MULDIV
+x{A985} @Defop MULDIVR
+x{A98C} @Defop MULDIVMOD
+x{A9A4} @Defop MULRSHIFT
+x{A9A5} @Defop MULRSHIFTR
+x{A9A6} @Defop MULRSHIFTC
+x{A9B4} @Defop(8u+1) MULRSHIFT#
+x{A9B5} @Defop(8u+1) MULRSHIFTR#
+x{A9B6} @Defop(8u+1) MULRSHIFTC#
+x{A9C4} @Defop LSHIFTDIV
+x{A9C5} @Defop LSHIFTDIVR
+x{A9C6} @Defop LSHIFTDIVC
+x{A9D4} @Defop(8u+1) LSHIFT#DIV
+x{A9D5} @Defop(8u+1) LSHIFT#DIVR
+x{A9D6} @Defop(8u+1) LSHIFT#DIVC
+x{AA} @Defop(8u+1) LSHIFT#
+x{AB} @Defop(8u+1) RSHIFT#
+x{AC} @Defop LSHIFT
+x{AD} @Defop RSHIFT
+x{AE} @Defop POW2
+x{B0} @Defop AND
+x{B1} @Defop OR
+x{B2} @Defop XOR
+x{B3} @Defop NOT
+x{B4} @Defop(8u+1) FITS
+x{B400} @Defop CHKBOOL
+x{B5} @Defop(8u+1) UFITS
+x{B500} @Defop CHKBIT
+x{B600} @Defop FITSX
+x{B601} @Defop UFITSX
+x{B602} @Defop BITSIZE
+x{B603} @Defop UBITSIZE
+x{B608} @Defop MIN
+x{B609} @Defop MAX
+x{B60A} dup @Defop MINMAX @Defop INTSORT2
+x{B60B} @Defop ABS
+x{B7} @Defop QUIET
+x{B7A0} @Defop QADD
+x{B7A1} @Defop QSUB
+x{B7A2} @Defop QSUBR
+x{B7A3} @Defop QNEGATE
+x{B7A4} @Defop QINC
+x{B7A5} @Defop QDEC
+x{B7A8} @Defop QMUL
+x{B7A904} @Defop QDIV
+x{B7A905} @Defop QDIVR
+x{B7A906} @Defop QDIVC
+x{B7A908} @Defop QMOD
+x{B7A90C} @Defop QDIVMOD
+x{B7A90D} @Defop QDIVMODR
+x{B7A90E} @Defop QDIVMODC
+x{B7A985} @Defop QMULDIVR
+x{B7A98C} @Defop QMULDIVMOD
+x{B7AC} @Defop QLSHIFT
+x{B7AD} @Defop QRSHIFT
+x{B7AE} @Defop QPOW2
+x{B7B0} @Defop QAND
+x{B7B1} @Defop QOR
+x{B7B2} @Defop QXOR
+x{B7B3} @Defop QNOT
+x{B7B4} @Defop(8u+1) QFITS
+x{B7B5} @Defop(8u+1) QUFITS
+x{B7B600} @Defop QFITSX
+x{B7B601} @Defop QUFITSX
+
+// advanced integer constants
+{ 0 { over 1 and 0= } { 1+ swap 2/ swap } while } : pow2decomp
+{ dup 8 fits { PUSHINT } {
+  dup pow2decomp over 1 = { nip nip PUSHPOW2 } {
+  over -1 = { nip nip PUSHNEGPOW2 } {
+  dup 20 >= { rot drop -rot PUSHINT swap LSHIFT# } {
+  { drop PUSHINT } {
+  not pow2decomp swap -1 = { nip PUSHPOW2DEC } {
+  drop PUSHINT
+  } cond } cond } cond } cond } cond } cond
+} dup : PUSHINTX : INTX
+
+// integer comparison
+x{B8} @Defop SGN
+x{B9} @Defop LESS
+x{BA} @Defop EQUAL
+x{BB} @Defop LEQ
+x{BC} @Defop GREATER
+x{BD} @Defop NEQ
+x{BE} @Defop GEQ
+x{BF} @Defop CMP
+x{C0} x{BA} @Defop(8i,alt) EQINT
+x{C000} @Defop ISZERO
+x{C1} x{B9} @Defop(8i,alt) LESSINT
+{ 1+ LESSINT } : LEQINT
+x{C100} @Defop ISNEG
+x{C101} @Defop ISNPOS
+x{C2} x{BC} @Defop(8i,alt) GTINT
+{ 1- GTINT } : GEQINT
+x{C200} @Defop ISPOS
+x{C2FF} @Defop ISNNEG
+x{C3} x{BD} @Defop(8i,alt) NEQINT
+x{C300} @Defop ISNZERO
+x{C4} @Defop ISNAN
+x{C5} @Defop CHKNAN
+
+// other comparison
+x{C700} @Defop SEMPTY
+x{C701} @Defop SDEMPTY
+x{C702} @Defop SREMPTY
+x{C703} @Defop SDFIRST
+x{C704} @Defop SDLEXCMP
+x{C705} @Defop SDEQ
+x{C708} @Defop SDPFX
+x{C709} @Defop SDPFXREV
+x{C70A} @Defop SDPPFX
+x{C70B} @Defop SDPPFXREV
+x{C70C} @Defop SDSFX
+x{C70D} @Defop SDSFXREV
+x{C70E} @Defop SDPSFX
+x{C70F} @Defop SDPSFXREV
+x{C710} @Defop SDCNTLEAD0
+x{C711} @Defop SDCNTLEAD1
+x{C712} @Defop SDCNTTRAIL0
+x{C713} @Defop SDCNTTRAIL1
+
+// cell serialization (Builder manipulation primitives)
+x{C8} @Defop NEWC
+x{C9} @Defop ENDC
+x{CA} @Defop(8u+1) STI
+x{CB} @Defop(8u+1) STU
+x{CC} @Defop STREF
+x{CD} dup @Defop STBREFR @Defop ENDCST
+x{CE} @Defop STSLICE
+x{CF00} @Defop STIX
+x{CF01} @Defop STUX
+x{CF02} @Defop STIXR
+x{CF03} @Defop STUXR
+x{CF04} @Defop STIXQ
+x{CF05} @Defop STUXQ
+x{CF06} @Defop STIXRQ
+x{CF07} @Defop STUXRQ
+x{CF08} @Defop(8u+1) STI_l
+x{CF09} @Defop(8u+1) STU_l
+x{CF0A} @Defop(8u+1) STIR
+x{CF0B} @Defop(8u+1) STUR
+x{CF0C} @Defop(8u+1) STIQ
+x{CF0D} @Defop(8u+1) STUQ
+x{CF0E} @Defop(8u+1) STIRQ
+x{CF0F} @Defop(8u+1) STURQ
+x{CF10} @Defop STREF_l
+x{CF11} @Defop STBREF
+x{CF12} @Defop STSLICE_l
+x{CF13} @Defop STB
+x{CF14} @Defop STREFR
+x{CF15} @Defop STBREFR_l
+x{CF16} @Defop STSLICER
+x{CF17} dup @Defop STBR @Defop BCONCAT
+x{CF18} @Defop STREFQ
+x{CF19} @Defop STBREFQ
+x{CF1A} @Defop STSLICEQ
+x{CF1B} @Defop STBQ
+x{CF1C} @Defop STREFRQ
+x{CF1D} @Defop STBREFRQ
+x{CF1E} @Defop STSLICERQ
+x{CF1F} dup @Defop STBRQ @Defop BCONCATQ
+x{CF20} @Defop(ref) STREFCONST
+{ <b x{CF21} s, rot ref, swap ref, @addopb } : STREF2CONST
+x{CF28} @Defop STILE4
+x{CF29} @Defop STULE4
+x{CF2A} @Defop STILE8
+x{CF2B} @Defop STULE8
+x{CF30} @Defop BDEPTH
+x{CF31} @Defop BBITS
+x{CF32} @Defop BREFS
+x{CF33} @Defop BBITREFS
+x{CF35} @Defop BREMBITS
+x{CF36} @Defop BREMREFS
+x{CF37} @Defop BREMBITREFS
+x{CF38} @Defop(8u+1) BCHKBITS#
+x{CF39} @Defop BCHKBITS
+x{CF3A} @Defop BCHKREFS
+x{CF3B} @Defop BCHKBITREFS
+x{CF3C} @Defop(8u+1) BCHKBITSQ#
+x{CF3D} @Defop BCHKBITSQ
+x{CF3E} @Defop BCHKREFSQ
+x{CF3F} @Defop BCHKBITREFSQ
+x{CF40} @Defop STZEROES
+x{CF41} @Defop STONES
+x{CF42} @Defop STSAME
+{ tuck sbitrefs swap 15 + swap @havebitrefs not
+  { swap PUSHSLICE STSLICER }
+  { over sbitrefs 2dup 57 3 2x<=
+    { rot x{CFC_} s, swap 2 u, over 6 + 3 >> tuck 3 u, 3 roll s,
+      -rot 3 << 2 + swap - @scomplete }
+    { 2drop swap PUSHSLICE STSLICER } cond
+  } cond
+} : STSLICECONST
+x{CF81} @Defop STZERO
+x{CF83} @Defop STONE
+
+// cell deserialization (CellSlice primitives)
+x{D0} @Defop CTOS
+x{D1} @Defop ENDS
+x{D2} @Defop(8u+1) LDI
+x{D3} @Defop(8u+1) LDU
+x{D4} @Defop LDREF
+x{D5} @Defop LDREFRTOS
+x{D6} @Defop(8u+1) LDSLICE
+x{D700} @Defop LDIX
+x{D701} @Defop LDUX
+x{D702} @Defop PLDIX
+x{D703} @Defop PLDUX
+x{D704} @Defop LDIXQ
+x{D705} @Defop LDUXQ
+x{D706} @Defop PLDIXQ
+x{D707} @Defop PLDUXQ
+x{D708} @Defop(8u+1) LDI_l
+x{D709} @Defop(8u+1) LDU_l
+x{D70A} @Defop(8u+1) PLDI
+x{D70B} @Defop(8u+1) PLDU
+x{D70C} @Defop(8u+1) LDIQ
+x{D70D} @Defop(8u+1) LDUQ
+x{D70E} @Defop(8u+1) PLDIQ
+x{D70F} @Defop(8u+1) PLDUQ
+{ dup 31 and abort"argument must be a multiple of 32" 5 >> 1-
+  <b x{D714_} s, swap 3 u, @addopb
+} : PLDUZ
+x{D718} @Defop LDSLICEX
+x{D719} @Defop PLDSLICEX
+x{D71A} @Defop LDSLICEXQ
+x{D71B} @Defop PLDSLICEXQ
+x{D71C} @Defop(8u+1) LDSLICE_l
+x{D71D} @Defop(8u+1) PLDSLICE
+x{D71E} @Defop(8u+1) LDSLICEQ
+x{D71F} @Defop(8u+1) PLDSLICEQ
+x{D720} @Defop SDCUTFIRST
+x{D721} @Defop SDSKIPFIRST
+x{D722} @Defop SDCUTLAST
+x{D723} @Defop SDSKIPLAST
+x{D724} @Defop SDSUBSTR
+x{D726} @Defop SDBEGINSX
+x{D727} @Defop SDBEGINSXQ
+{ tuck sbits tuck 5 + 3 >> swap x{D72A_} s, over 7 u, 3 roll s,
+  -rot 3 << 3 + swap - @scomplete } : SDBEGINS:imm
+{ tuck sbitrefs abort"no references allowed in slice" dup 26 <=
+  { drop <b rot SDBEGINS:imm @addopb }
+  { @havebits
+    { swap SDBEGINS:imm }
+    { swap PUSHSLICE SDBEGINSX
+    } cond
+  } cond
+} : SDBEGINS
+{ tuck sbits tuck 5 + 3 >> swap x{D72E_} s, over 7 u, 3 roll s,
+  -rot 3 << 3 + swap - @scomplete } : SDBEGINSQ:imm
+{ tuck sbitrefs abort"no references allowed in slice" dup 26 <=
+  { drop <b rot SDBEGINSQ:imm @addopb }
+  { @havebits
+    { swap SDBEGINSQ:imm }
+    { swap PUSHSLICE SDBEGINSXQ
+    } cond
+  } cond
+} : SDBEGINSQ
+x{D730} @Defop SCUTFIRST
+x{D731} @Defop SSKIPFIRST
+x{D732} @Defop SCUTLAST
+x{D733} @Defop SSKIPLAST
+x{D734} @Defop SUBSLICE
+x{D736} @Defop SPLIT
+x{D737} @Defop SPLITQ
+x{D741} @Defop SCHKBITS
+x{D742} @Defop SCHKREFS
+x{D743} @Defop SCHKBITREFS
+x{D745} @Defop SCHKBITSQ
+x{D746} @Defop SCHKREFSQ
+x{D747} @Defop SCHKBITREFSQ
+x{D748} @Defop PLDREFVAR
+x{D749} @Defop SBITS
+x{D74A} @Defop SREFS
+x{D74B} @Defop SBITREFS
+{ <b x{D74E_} s, swap 2 u, @addopb } : PLDREFIDX
+x{D74C} @Defop PLDREF
+x{D750} @Defop LDILE4
+x{D751} @Defop LDULE4
+x{D752} @Defop LDILE8
+x{D753} @Defop LDULE8
+x{D754} @Defop PLDILE4
+x{D755} @Defop PLDULE4
+x{D756} @Defop PLDILE8
+x{D757} @Defop PLDULE8
+x{D758} @Defop LDILE4Q
+x{D759} @Defop LDULE4Q
+x{D75A} @Defop LDILE8Q
+x{D75B} @Defop LDULE8Q
+x{D75C} @Defop PLDILE4Q
+x{D75D} @Defop PLDULE4Q
+x{D75E} @Defop PLDILE8Q
+x{D75F} @Defop PLDULE8Q
+x{D760} @Defop LDZEROES
+x{D761} @Defop LDONES
+x{D762} @Defop LDSAME
+x{D764} @Defop SDEPTH
+x{D765} @Defop CDEPTH
+//
+// continuation / flow control primitives
+x{D8} dup @Defop EXECUTE @Defop CALLX
+x{D9} @Defop JMPX
+{ dup 1+
+  { <b x{DA} s, rot 4 u, swap 4 u, }
+  { drop <b x{DB0} s, swap 4 u,
+  } cond @addopb
+} : CALLXARGS
+x{DB1} @Defop(4u) JMPXARGS
+x{DB2} @Defop(4u) RETARGS
+x{DB30} dup @Defop RET @Defop RETTRUE
+x{DB31} dup @Defop RETALT @Defop RETFALSE
+x{DB32} dup @Defop BRANCH @Defop RETBOOL
+x{DB34} @Defop CALLCC
+x{DB35} @Defop JMPXDATA
+{ dup 1+ 0= { 16 + } if
+  <b x{DB36} rot 4 u, swap 4 u, @addopb
+} : CALLCCARGS
+x{DB38} @Defop CALLXVARARGS
+x{DB39} @Defop RETVARARGS
+x{DB3A} @Defop JMPXVARARGS
+x{DB3B} @Defop CALLCCVARARGS
+x{DB3C} @Defop(ref) CALLREF
+x{DB3D} @Defop(ref) JMPREF
+x{DB3E} @Defop(ref) JMPREFDATA
+x{DB3F} @Defop RETDATA
+// conditional and iterated execution primitives
+x{DC} @Defop IFRET
+x{DD} @Defop IFNOTRET
+x{DE} @Defop IF
+x{DF} @Defop IFNOT
+' IFNOTRET : IF:
+' IFRET : IFNOT:
+x{E0} @Defop IFJMP
+x{E1} @Defop IFNOTJMP
+x{E2} @Defop IFELSE
+
+x{E300} @Defop(ref) IFREF
+x{E301} @Defop(ref) IFNOTREF
+x{E302} @Defop(ref) IFJMPREF
+x{E303} @Defop(ref) IFNOTJMPREF
+x{E30D} @Defop(ref) IFREFELSE
+x{E30E} @Defop(ref) IFELSEREF
+x{E30F} @Defop(ref*2) IFREFELSEREF
+
+{ 16 1 @havebitrefs nip } : @refop-fits?
+// b b1 [e0 e1 e2] -- b'
+{ -rot dup @cont-empty? { drop swap 0 } {
+  2dup @cont-fits? { rot 1 } {
+  over @refop-fits? { b> rot 2 } {
+  swap @| swap 2dup @cont-fits? { rot 1 } {
+  b> rot 2
+  } cond } cond } cond } cond
+  [] execute
+} : @run-cont-op
+{ triple 1 ' @run-cont-op does create } : @def-cont-op
+{ } { PUSHCONT IF } { IFREF } @def-cont-op IF-cont
+{ IFRET } { PUSHCONT IFJMP } { IFJMPREF } @def-cont-op IFJMP-cont
+{ } { PUSHCONT IFNOT } { IFNOTREF } @def-cont-op IFNOT-cont
+{ IFNOTRET } { PUSHCONT IFNOTJMP } { IFNOTJMPREF } @def-cont-op IFNOTJMP-cont
+{ dup 2over rot } : 3dup
+
+recursive IFELSE-cont2 {
+  dup @cont-empty? { drop IF-cont } {
+  over @cont-empty? { nip IFNOT-cont } {
+  3dup @two-cont-fit? { -rot PUSHCONT swap PUSHCONT IFELSE } {
+  3dup nip @cont-ref-fit? { rot swap PUSHCONT swap b> IFREFELSE } {
+  3dup drop @cont-ref-fit? { -rot PUSHCONT swap b> IFELSEREF } {
+  rot 32 2 @havebitrefs { rot b> rot b> IFREFELSEREF } {
+  @| -rot IFELSE-cont2
+  } cond } cond } cond } cond } cond } cond
+} swap !
+
+{ }> IF-cont } : }>IF
+{ }> IFNOT-cont } : }>IFNOT
+{ }> IFJMP-cont } : }>IFJMP
+{ }> IFNOTJMP-cont } : }>IFNOTJMP
+{ { @normal? IFJMP-cont } @doafter<{ } : IFJMP:<{
+{ { @normal? IFNOTJMP-cont } @doafter<{ } : IFNOTJMP:<{
+{ `else @endblk } : }>ELSE<{
+{ `else: @endblk } : }>ELSE:
+{ 1 { swap @normal? swap IFELSE-cont2 } does @doafter<{ } : @doifelse
+{ 1 { swap @normal? IFELSE-cont2 } does @doafter<{ } : @doifnotelse
+{
+  { dup `else eq?
+    { drop @doifelse }
+    { dup `else: eq?
+      { drop IFJMP-cont }
+      { @normal? IF-cont
+      } cond
+    } cond
+  } @doafter<{
+} : IF:<{
+{
+  { dup `else eq?
+    { drop @doifnotelse }
+    { dup `else: eq?
+      { drop IFNOTJMP-cont }
+      { @normal? IFNOT-cont
+      } cond
+    } cond
+  } @doafter<{
+} : IFNOT:<{
+
+x{E304} @Defop CONDSEL
+x{E305} @Defop CONDSELCHK
+x{E308} @Defop IFRETALT
+x{E309} @Defop IFNOTRETALT
+{ <b x{E39_} swap 5 u, @addopb } : IFBITJMP
+{ <b x{E3B_} swap 5 u, @addopb } : IFNBITJMP
+{ <b x{E3D_} swap 5 u, swap ref, @addopb } : IFBITJMPREF
+{ <b x{E3F_} swap 5 u, swap ref, @addopb } : IFNBITJMPREF
+
+x{E4} @Defop REPEAT
+x{E5} dup @Defop REPEATEND @Defop REPEAT:
+x{E6} @Defop UNTIL
+x{E7} dup @Defop UNTILEND @Defop UNTIL:
+x{E8} @Defop WHILE
+x{E9} @Defop WHILEEND
+x{EA} @Defop AGAIN
+x{EB} dup @Defop AGAINEND @Defop AGAIN:
+
+{ `do @endblk } : }>DO<{
+{ `do: @endblk } : }>DO:
+{ }> PUSHCONT REPEAT } : }>REPEAT
+{ { @normal? PUSHCONT REPEAT } @doafter<{ } : REPEAT:<{
+{ }> PUSHCONT UNTIL } : }>UNTIL
+{ { @normal? PUSHCONT UNTIL } @doafter<{ } : UNTIL:<{
+{ PUSHCONT { @normal? PUSHCONT WHILE } @doafter<{ } : @dowhile
+{
+  { dup `do eq?
+    { drop @dowhile }
+    { `do: eq? not abort"`}>DO<{` expected" PUSHCONT WHILEEND
+    } cond
+  } @doafter<{
+} : WHILE:<{
+{ }> PUSHCONT AGAIN } : }>AGAIN
+{ { @normal? PUSHCONT AGAIN } @doafter<{ } : AGAIN:<{
+
+x{E314} @Defop REPEATBRK
+x{E315} @Defop REPEATENDBRK
+x{E316} @Defop UNTILBRK
+x{E317} dup @Defop UNTILENDBRK @Defop UNTILBRK:
+x{E318} @Defop WHILEBRK
+x{E319} @Defop WHILEENDBRK
+x{E31A} @Defop AGAINBRK
+x{E31B} dup @Defop AGAINENDBRK @Defop AGAINBRK:
+
+{ }> PUSHCONT REPEATBRK } : }>REPEATBRK
+{ { @normal? PUSHCONT REPEATBRK } @doafter<{ } : REPEATBRK:<{
+{ }> PUSHCONT UNTILBRK } : }>UNTILBRK
+{ { @normal? PUSHCONT UNTILBRK } @doafter<{ } : UNTILBRK:<{
+{ PUSHCONT { @normal? PUSHCONT WHILEBRK } @doafter<{ } : @dowhile
+{
+  { dup `do eq?
+    { drop @dowhile }
+    { `do: eq? not abort"`}>DO<{` expected" PUSHCONT WHILEENDBRK
+    } cond
+  } @doafter<{
+} : WHILEBRK:<{
+{ }> PUSHCONT AGAINBRK } : }>AGAINBRK
+{ { @normal? PUSHCONT AGAINBRK } @doafter<{ } : AGAINBRK:<{
+
+
+//
+// continuation stack manipulation and continuation creation
+//
+{ <b x{EC} s, rot 4 u, swap dup 1+ { 16 + } ifnot 4 u, @addopb } : SETCONTARGS
+{ 0 swap SETCONTARGS } : SETNUMARGS
+x{ED0} @Defop(4u) RETURNARGS
+x{ED10} @Defop RETURNVARARGS
+x{ED11} @Defop SETCONTVARARGS
+x{ED12} @Defop SETNUMVARARGS
+x{ED1E} @Defop BLESS
+x{ED1F} @Defop BLESSVARARGS
+{ <b x{EE} s, rot 4 u, swap dup 1+ { 16 + } ifnot 4 u, @addopb } : BLESSARGS
+{ 0 swap BLESSARGS } : BLESSNUMARGS
+//
+// control register and continuation savelist manipulation
+// x{ED4} Defop(c) PUSHCTR
+// x{ED5} Defop(c) POPCTR
+{ c4 PUSHCTR } : PUSHROOT
+{ c4 POPCTR } : POPROOT
+x{ED6} dup @Defop(c) SETCONTCTR @Defop(c) SETCONT
+x{ED7} @Defop(c) SETRETCTR
+x{ED8} @Defop(c) SETALTCTR
+x{ED9} dup @Defop(c) POPSAVE @Defop(c) POPCTRSAVE
+x{EDA} dup @Defop(c) SAVE @Defop(c) SAVECTR
+x{EDB} dup @Defop(c) SAVEALT @Defop(c) SAVEALTCTR
+x{EDC} dup @Defop(c) SAVEBOTH @Defop(c) SAVEBOTHCTR
+x{EDE0} @Defop PUSHCTRX
+x{EDE1} @Defop POPCTRX
+x{EDE2} @Defop SETCONTCTRX
+x{EDF0} dup @Defop BOOLAND @Defop COMPOS
+x{EDF1} dup @Defop BOOLOR @Defop COMPOSALT
+x{EDF2} @Defop COMPOSBOTH
+x{EDF3} @Defop ATEXIT
+{ }> PUSHCONT ATEXIT } : }>ATEXIT
+{ { @normal? PUSHCONT ATEXIT } @doafter<{ } : ATEXIT:<{
+x{EDF4} @Defop ATEXITALT
+{ }> PUSHCONT ATEXITALT } : }>ATEXITALT
+{ { @normal? PUSHCONT ATEXITALT } @doafter<{ } : ATEXITALT:<{
+x{EDF5} @Defop SETEXITALT
+{ }> PUSHCONT SETEXITALT } : }>SETEXITALT
+{ { @normal? PUSHCONT SETEXITALT } @doafter<{ } : SETEXITALT:<{
+x{EDF6} @Defop THENRET
+x{EDF7} @Defop THENRETALT
+x{EDF8} @Defop INVERT
+x{EDF9} @Defop BOOLEVAL
+x{EDFA} @Defop SAMEALT
+x{EDFB} @Defop SAMEALTSAVE
+// x{EE} is BLESSARGS
+//
+// dictionary subroutine call/jump primitives
+{ c3 PUSH EXECUTE } : CALLVAR
+{ c3 PUSH JMPX } : JMPVAR
+{ c3 PUSH } : PREPAREVAR
+{ dup 14 ufits {
+    dup 8 ufits {
+      <b x{F0} s, swap 8 u, } {
+      <b x{F12_} s, swap 14 u,
+    } cond @addopb } {
+    PUSHINT CALLVAR
+  } cond
+} dup : CALL : CALLDICT
+{ dup 14 ufits
+  { <b x{F16_} s, swap 14 u, @addopb }
+  { PUSHINT JMPVAR } cond
+} dup : JMP : JMPDICT
+{ dup 14 ufits
+  { <b x{F1A_} s, swap 14 u, @addopb }
+  { PUSHINT c3 PREPAREVAR } cond
+} dup : PREPARE : PREPAREDICT
+//
+// inline support
+{ dup sbits { @addop } {
+  dup srefs 1- abort"exactly one reference expected in inline"
+  ref@ CALLREF } cond
+} : INLINE
+//
+// throwing and handling exceptions
+{ dup 6 ufits
+  { <b x{F22_} s, swap 6 u, }
+  { <b x{F2C4_} s, swap 11 u,
+  } cond
+@addopb } : THROW
+{ dup 6 ufits
+  { <b x{F26_} s, swap 6 u, }
+  { <b x{F2D4_} s, swap 11 u,
+  } cond
+@addopb } : THROWIF
+{ dup 6 ufits
+  { <b x{F2A_} s, swap 6 u, }
+  { <b x{F2E4_} s, swap 11 u,
+  } cond
+@addopb } : THROWIFNOT
+{ <b x{F2CC_} s, swap 11 u, @addopb } : THROWARG
+{ <b x{F2DC_} s, swap 11 u, @addopb } : THROWARGIF
+{ <b x{F2EC_} s, swap 11 u, @addopb } : THROWARGIFNOT
+x{F2F0} @Defop THROWANY
+x{F2F1} @Defop THROWARGANY
+x{F2F2} @Defop THROWANYIF
+x{F2F3} @Defop THROWARGANYIF
+x{F2F4} @Defop THROWANYIFNOT
+x{F2F5} @Defop THROWARGANYIFNOT
+x{F2FF} @Defop TRY
+x{F3} @Defop(4u,4u) TRYARGS
+{ `catch @endblk } : }>CATCH<{
+{ PUSHCONT { @normal? PUSHCONT TRY } @doafter<{ } : @trycatch
+{
+  { `catch eq? not abort"`}>CATCH<{` expected" @trycatch
+  } @doafter<{
+} : TRY:<{
+//
+// dictionary manipulation
+' NULL : NEWDICT
+' ISNULL : DICTEMPTY
+' STSLICE : STDICTS
+x{F400} dup @Defop STDICT @Defop STOPTREF
+x{F401} dup @Defop SKIPDICT @Defop SKIPOPTREF
+x{F402} @Defop LDDICTS
+x{F403} @Defop PLDDICTS
+x{F404} dup @Defop LDDICT @Defop LDOPTREF
+x{F405} dup @Defop PLDDICT @Defop PLDOPTREF
+x{F406} @Defop LDDICTQ
+x{F407} @Defop PLDDICTQ
+
+x{F40A} @Defop DICTGET
+x{F40B} @Defop DICTGETREF
+x{F40C} @Defop DICTIGET
+x{F40D} @Defop DICTIGETREF
+x{F40E} @Defop DICTUGET
+x{F40F} @Defop DICTUGETREF
+
+x{F412} @Defop DICTSET
+x{F413} @Defop DICTSETREF
+x{F414} @Defop DICTISET
+x{F415} @Defop DICTISETREF
+x{F416} @Defop DICTUSET
+x{F417} @Defop DICTUSETREF
+x{F41A} @Defop DICTSETGET
+x{F41B} @Defop DICTSETGETREF
+x{F41C} @Defop DICTISETGET
+x{F41D} @Defop DICTISETGETREF
+x{F41E} @Defop DICTUSETGET
+x{F41F} @Defop DICTUSETGETREF
+
+x{F422} @Defop DICTREPLACE
+x{F423} @Defop DICTREPLACEREF
+x{F424} @Defop DICTIREPLACE
+x{F425} @Defop DICTIREPLACEREF
+x{F426} @Defop DICTUREPLACE
+x{F427} @Defop DICTUREPLACEREF
+x{F42A} @Defop DICTREPLACEGET
+x{F42B} @Defop DICTREPLACEGETREF
+x{F42C} @Defop DICTIREPLACEGET
+x{F42D} @Defop DICTIREPLACEGETREF
+x{F42E} @Defop DICTUREPLACEGET
+x{F42F} @Defop DICTUREPLACEGETREF
+
+x{F432} @Defop DICTADD
+x{F433} @Defop DICTADDREF
+x{F434} @Defop DICTIADD
+x{F435} @Defop DICTIADDREF
+x{F436} @Defop DICTUADD
+x{F437} @Defop DICTUADDREF
+x{F43A} @Defop DICTADDGET
+x{F43B} @Defop DICTADDGETREF
+x{F43C} @Defop DICTIADDGET
+x{F43D} @Defop DICTIADDGETREF
+x{F43E} @Defop DICTUADDGET
+x{F43F} @Defop DICTUADDGETREF
+
+x{F441} @Defop DICTSETB
+x{F442} @Defop DICTISETB
+x{F443} @Defop DICTUSETB
+x{F445} @Defop DICTSETGETB
+x{F446} @Defop DICTISETGETB
+x{F447} @Defop DICTUSETGETB
+
+x{F449} @Defop DICTREPLACEB
+x{F44A} @Defop DICTIREPLACEB
+x{F44B} @Defop DICTUREPLACEB
+x{F44D} @Defop DICTREPLACEGETB
+x{F44E} @Defop DICTIREPLACEGETB
+x{F44F} @Defop DICTUREPLACEGETB
+
+x{F451} @Defop DICTADDB
+x{F452} @Defop DICTIADDB
+x{F453} @Defop DICTUADDB
+x{F455} @Defop DICTADDGETB
+x{F456} @Defop DICTIADDGETB
+x{F457} @Defop DICTUADDGETB
+
+x{F459} @Defop DICTDEL
+x{F45A} @Defop DICTIDEL
+x{F45B} @Defop DICTUDEL
+
+x{F462} @Defop DICTDELGET
+x{F463} @Defop DICTDELGETREF
+x{F464} @Defop DICTIDELGET
+x{F465} @Defop DICTIDELGETREF
+x{F466} @Defop DICTUDELGET
+x{F467} @Defop DICTUDELGETREF
+
+x{F469} @Defop DICTGETOPTREF
+x{F46A} @Defop DICTIGETOPTREF
+x{F46B} @Defop DICTUGETOPTREF
+x{F46D} @Defop DICTSETGETOPTREF
+x{F46E} @Defop DICTISETGETOPTREF
+x{F46F} @Defop DICTUSETGETOPTREF
+
+x{F470} @Defop PFXDICTSET
+x{F471} @Defop PFXDICTREPLACE
+x{F472} @Defop PFXDICTADD
+x{F473} @Defop PFXDICTDEL
+
+x{F474} @Defop DICTGETNEXT
+x{F475} @Defop DICTGETNEXTEQ
+x{F476} @Defop DICTGETPREV
+x{F477} @Defop DICTGETPREVEQ
+x{F478} @Defop DICTIGETNEXT
+x{F479} @Defop DICTIGETNEXTEQ
+x{F47A} @Defop DICTIGETPREV
+x{F47B} @Defop DICTIGETPREVEQ
+x{F47C} @Defop DICTUGETNEXT
+x{F47D} @Defop DICTUGETNEXTEQ
+x{F47E} @Defop DICTUGETPREV
+x{F47F} @Defop DICTUGETPREVEQ
+
+x{F482} @Defop DICTMIN
+x{F483} @Defop DICTMINREF
+x{F484} @Defop DICTIMIN
+x{F485} @Defop DICTIMINREF
+x{F486} @Defop DICTUMIN
+x{F487} @Defop DICTUMINREF
+x{F48A} @Defop DICTMAX
+x{F48B} @Defop DICTMAXREF
+x{F48C} @Defop DICTIMAX
+x{F48D} @Defop DICTIMAXREF
+x{F48E} @Defop DICTUMAX
+x{F48F} @Defop DICTUMAXREF
+
+x{F492} @Defop DICTREMMIN
+x{F493} @Defop DICTREMMINREF
+x{F494} @Defop DICTIREMMIN
+x{F495} @Defop DICTIREMMINREF
+x{F496} @Defop DICTUREMMIN
+x{F497} @Defop DICTUREMMINREF
+x{F49A} @Defop DICTREMMAX
+x{F49B} @Defop DICTREMMAXREF
+x{F49C} @Defop DICTIREMMAX
+x{F49D} @Defop DICTIREMMAXREF
+x{F49E} @Defop DICTUREMMAX
+x{F49F} @Defop DICTUREMMAXREF
+
+x{F4A0} @Defop DICTIGETJMP
+x{F4A1} @Defop DICTUGETJMP
+x{F4A2} @Defop DICTIGETEXEC
+x{F4A3} @Defop DICTUGETEXEC
+{ dup sbitrefs tuck 1 > swap 1 <> or abort"not a dictionary" swap 1 u@ over <> abort"not a dictionary" } : @chkdicts
+{ dup null? tuck { <s } ifnot drop not } : @chkdict
+{ over @chkdict
+  { swap <b x{F4A6_} s, swap ref, swap 10 u, @addopb }
+  { nip swap NEWDICT swap PUSHINT }
+  cond
+} : DICTPUSHCONST
+x{F4A8} @Defop PFXDICTGETQ
+x{F4A9} @Defop PFXDICTGET
+x{F4AA} @Defop PFXDICTGETJMP
+x{F4AB} @Defop PFXDICTGETEXEC
+{ over @chkdict
+  { swap <b x{F4AE_} s, swap ref, swap 10 u, @addopb
+  } if
+} dup : PFXDICTCONSTGETJMP : PFXDICTSWITCH
+
+x{F4B1} @Defop SUBDICTGET
+x{F4B2} @Defop SUBDICTIGET
+x{F4B3} @Defop SUBDICTUGET
+x{F4B5} @Defop SUBDICTRPGET
+x{F4B6} @Defop SUBDICTIRPGET
+x{F4B7} @Defop SUBDICTURPGET
+
+x{F4BC} @Defop DICTIGETJMPZ
+x{F4BD} @Defop DICTUGETJMPZ
+x{F4BE} @Defop DICTIGETEXECZ
+x{F4BF} @Defop DICTUGETEXECZ
+
+//
+// blockchain-specific primitives
+
+x{F800} @Defop ACCEPT
+x{F801} @Defop SETGASLIMIT
+x{F80F} @Defop COMMIT
+
+x{F810} @Defop RANDU256
+x{F811} @Defop RAND
+x{F814} @Defop SETRAND
+x{F815} dup @Defop ADDRAND @Defop RANDOMIZE
+
+x{F82} @Defop(4u) GETPARAM
+x{F823} @Defop NOW
+x{F824} @Defop BLOCKLT
+x{F825} @Defop LTIME
+x{F826} @Defop RANDSEED
+x{F827} @Defop BALANCE
+x{F828} @Defop MYADDR
+x{F829} @Defop CONFIGROOT
+x{F830} @Defop CONFIGDICT
+x{F832} @Defop CONFIGPARAM
+x{F833} @Defop CONFIGOPTPARAM
+
+x{F840} @Defop GETGLOBVAR
+{ dup 1 31 @rangechk <b x{F85_} s, swap 5 u, @addopb } : GETGLOB
+x{F860} @Defop SETGLOBVAR
+{ dup 1 31 @rangechk <b x{F87_} s, swap 5 u, @addopb } : SETGLOB
+
+x{F900} @Defop HASHCU
+x{F901} @Defop HASHSU
+x{F902} @Defop SHA256U
+x{F910} @Defop CHKSIGNU
+x{F911} @Defop CHKSIGNS
+
+x{F940} @Defop CDATASIZEQ
+x{F941} @Defop CDATASIZE
+x{F942} @Defop SDATASIZEQ
+x{F943} @Defop SDATASIZE
+
+x{FA00} dup @Defop LDGRAMS @Defop LDVARUINT16
+x{FA01} @Defop LDVARINT16
+x{FA02} dup @Defop STGRAMS @Defop STVARUINT16
+x{FA03} @Defop STVARINT16
+
+x{FA40} @Defop LDMSGADDR
+x{FA41} @Defop LDMSGADDRQ
+x{FA42} @Defop PARSEMSGADDR
+x{FA43} @Defop PARSEMSGADDRQ
+x{FA44} @Defop REWRITESTDADDR
+x{FA45} @Defop REWRITESTDADDRQ
+x{FA46} @Defop REWRITEVARADDR
+x{FA47} @Defop REWRITEVARADDRQ
+
+x{FB00} @Defop SENDRAWMSG
+x{FB02} @Defop RAWRESERVE
+x{FB03} @Defop RAWRESERVEX
+x{FB04} @Defop SETCODE
+x{FB06} @Defop SETLIBCODE
+x{FB07} @Defop CHANGELIB
+
+//
+// debug primitives
+
+{ dup 0 239 @-range abort"debug selector out of range"
+  <b x{FE} s, swap 8 u, @addopb
+} : DEBUG
+{ dup $len 1- <b x{FEF} s, swap 4 u, swap $, @addopb
+} : DEBUGSTR
+{ over $len <b x{FEF} s, swap 4 u, swap 8 u, swap $, @addopb
+} : DEBUGSTRI
+
+x{FE00} @Defop DUMPSTK
+{ 1 15 @rangechk <b x{FE0} s, swap 4 u, @addopb
+} : DUMPSTKTOP
+x{FE10} @Defop HEXDUMP
+x{FE11} @Defop HEXPRINT
+x{FE12} @Defop BINDUMP
+x{FE13} @Defop BINPRINT
+x{FE14} @Defop STRDUMP
+x{FE15} @Defop STRPRINT
+x{FE1E} @Defop DEBUGOFF
+x{FE1F} @Defop DEBUGON
+x{FE2} @Defop(s) DUMP
+x{FE3} @Defop(s) PRINT
+' DEBUGSTR : DUMPTOSFMT
+{ 0 DEBUGSTRI } : LOGSTR
+{ 1 DEBUGSTRI } : PRINTSTR
+x{FEF000} @Defop LOGFLUSH
+
+//
+// codepage primitives
+x{FF00} @Defop SETCP0
+x{FFF0} @Defop SETCPX
+{ dup -14 239 @-range abort"codepage out of range"
+  255 and <b x{FF} s, swap 8 u, @addopb
+} : SETCP
+
+//
+// provisions for defining programs consisting of several mutually-recursive procedures
+//
+variable @proccnt
+variable @proclist
+variable @procdict
+variable @procinfo
+variable @gvarcnt
+variable asm-mode  1 asm-mode !
+19 constant @procdictkeylen
+32 constant @zcount
+{ pair @proclist @ cons @proclist ! } : @proclistadd
+{ @procinfo @ @procdictkeylen idict@ { 16 i@ } { 0 } cond } : @procinfo@
+{ <b rot 16 i, swap @procinfo @ @procdictkeylen b>idict!
+  not abort"cannot add key to procedure info dictionary"
+  @procinfo !
+} : @procinfo!
+// ( x v1 v2 -- )
+{ not 2 pick @procinfo@ and xor swap @procinfo! } : @procinfo~!
+// ( s i f -- )
+{ over @procdictkeylen fits not abort"procedure index out of range"
+  over swap dup @procinfo~!  2dup @proclistadd
+  1 'nop does swap 0 (create)
+} : @declproc
+{ 1 'nop does swap 0 (create) } : @declglobvar
+{ @proccnt @ 1+ dup @proccnt ! 1 @declproc } : @newproc
+{ @gvarcnt @ 1+ dup @gvarcnt ! @declglobvar } : @newglobvar
+{ 0 =: main  @proclist null!  @proccnt 0!  @gvarcnt 0!
+  { bl word @newproc } : NEWPROC
+  { bl word dup (def?) ' drop ' @newproc cond } : DECLPROC
+  { bl word dup find
+    { nip execute <> abort"method redefined with different id" }
+    { swap 17 @declproc }
+  cond } : DECLMETHOD
+  { bl word @newglobvar } : DECLGLOBVAR
+  "main" 0 @proclistadd
+  dictnew dup @procdict !
+  @procinfo !  16 0 @procinfo!
+} : PROGRAM{
+{ over sbits < { s>c <b swap ref, b> <s } if } : @adj-long-proc
+{ // i s l
+  @adj-long-proc over @procdict @ @procdictkeylen
+  idict!+ not abort"cannot define procedure, redefined?"
+  @procdict !  2 2 @procinfo~!
+} : @def-proc
+{ @procinfo @ null? not } : @have-procinfo?
+{ @have-procinfo? { 4 4 @procinfo~! } { drop } cond } : @proc-inlined
+{ @have-procinfo? { 8 8 @procinfo~! } { drop } cond } : @proc-called
+{ 1000 @def-proc } : PROC
+{ 0 @def-proc } : PROCREF
+{ @procdict @ @procdictkeylen idict@ abort"procedure already defined"
+} : @fail-ifdef
+{ u@?+ { swap abort"first bits are not zeroes" } if } : @cut-zeroes
+{ over @fail-ifdef
+  2 { rot @normal? rot b> <s @zcount @cut-zeroes swap @def-proc drop } does
+  null swap @doafter<{ 0 @zcount u,
+} : @PROC:<{
+{ 1000 @PROC:<{ } : PROC:<{
+{ 0 @PROC:<{ } : PROCREF:<{
+{ dup @proc-called CALLDICT } dup : CALL : CALLDICT
+{ dup @proc-called JMPDICT } dup : JMP : JMPDICT
+{ dup @proc-called PREPAREDICT } dup : PREPARE : PREPAREDICT
+{ dup @procdict @ @procdictkeylen idict@
+  { swap @proc-inlined INLINE } { CALLDICT } cond
+} dup : INLINECALL : INLINECALLDICT
+{ 0 @procdict @ @procdictkeylen idict@ not abort"`main` procedure not defined" drop
+} : @chkmaindef
+{ @procdict @ @procdictkeylen idict- drop @procdict ! } : @remove-proc
+{ ."Procedure `" over type ."` index=" 2 pick . ." flags=0x" dup x. cr } : @showprocinfo
+// ( proc_name proc_idx f -- )  f:+1=declared, +2=defined, +4=inlined, +8=called, +16=method
+{ // @showprocinfo
+  dup 0x1a and 2 = asm-mode @ 3 and and ?dup {
+    2 and {
+      over ."Warning: removing (inlined) procedure `" type ."` from call dictionary" cr
+    } if
+    2 pick @remove-proc
+  } if  // remove unused procs
+  dup 0xc and 0xc = asm-mode @ 4 and and {
+    over ."Warning: inline procedure `" type ."` is not always inlined" cr
+  } if
+  dup 0x1e and 2 = asm-mode @ 8 and and {
+    over ."Warning: procedure `" type ."` defined but not used" cr
+  } if
+  drop 2drop
+} : @chkprocdef
+{ @chkmaindef
+  @proclist @
+  @proclist @ { dup null? not } {
+    uncons swap unpair over find not
+    { drop +": undefined procedure name in list" abort } if
+    drop tuck @procdict @ @procdictkeylen idict@ not
+    { +": procedure declared but left undefined" abort } if
+    drop swap 2dup @procinfo@ @chkprocdef (forget)
+  } while
+  drop @proclist null! @procinfo null! @proccnt 0!
+  @procdict dup @ swap null!
+} : }END
+{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMPZ 11 THROWARG }> } : }END>
+{ }END> b> } : }END>c
+{ }END>c <s } : }END>s
+
+
+0 constant recv_internal
+-1 constant recv_external
+-2 constant run_ticktock
+-3 constant split_prepare
+-4 constant split_install
+
+{ asm-mode 0 3 ~! } : asm-no-remove-unused
+{ asm-mode 1 1 ~! } : asm-remove-unused   // enabled by default
+{ asm-mode 3 3 ~! } : asm-warn-remove-unused
+{ asm-mode 4 4 ~! } : asm-warn-inline-mix
+{ asm-mode 0 4 ~! } : asm-no-warn-inline-mix  // disabled by default
+{ asm-mode 8 8 ~! } : asm-warn-unused
+{ asm-mode 0 8 ~! } : asm-no-warn-unused  // disabled by default
+
+// ( c -- )   add vm library for later use with runvmcode
+{ <b over ref, b> <s swap hash vmlibs @ 256 udict! not abort"cannot add library" vmlibs ! } : add-lib
+// ( x -- c ) make library reference cell
+{ <b 2 8 u, swap 256 u, b>spec } : hash>libref
+// ( c -- c' )
+{ hash hash>libref } : >libref
diff --git a/src/toncli/lib/fift-libs/TonUtil.fif b/src/toncli/lib/fift-libs/TonUtil.fif
index 1b978a2..a417c1c 100644
--- a/src/toncli/lib/fift-libs/TonUtil.fif
+++ b/src/toncli/lib/fift-libs/TonUtil.fif
@@ -268,3 +268,113 @@ def? config-valid? {
   config-valid?
   } cond } cond } cond
 } : is-valid-config?
+
+// Get anycast depth / rewrite_pfx or return 0
+// ( S -- x y S )
+{
+    // maybe
+    1 u@+ swap 0 >
+    {
+        // anycast_info$_ depth:(#<= 30) { depth >= 1 }
+        //    rewrite_pfx:(bits depth) = Anycast;
+        30 u@+ swap // get depth
+
+        dup 1 > {
+            dup 2 roll swap u@+ // get rewrite_pfx
+            // return depth, rewrite_pfx, slice
+        }
+        {
+            drop // drop depth (<=1)
+            0 0 2 roll // set anycast to none
+        } cond
+    }
+    {
+        0 0 2 roll // set anycast to none
+    } cond
+} : maybe-anycast
+
+// Rewrite first bits of addr with anycast info
+{ // input: anycast depth, rewrite_pfx, workchain, slice, address length
+    4 -roll
+    3 roll dup dup 0 = { 2drop 2 roll drop }
+    {
+        rot swap u@+ swap drop
+        3 roll
+        <b swap 3 roll u, b> <s swap |+
+    } cond // rewrite first bits of address with rewrite_pfx
+    2 roll
+    u@+ // get address
+} : parse-address-with-anycast
+
+// Parse Slice S and return:
+// 0 `addr_none S - if addr_none$00 is parsed
+// addr `addr_extern S - if addr_extern$01 is parsed
+// wc addr `addr_std S - if addr_std$10 is parsed
+// wc addr `addr_var S - if addr_var$11 is parsed
+// ( S -- 0 A S or addr A S or wc addr A S )
+{ 2 u@+ swap dup 0>  // Get addr: addr_none$00 / addr_extern$01 / addr_std$10 / addr_var$11
+    { // if greater that zero
+       dup 1 >
+       {
+            2 =
+            {
+                // if addr_std$10
+                // anycast:(Maybe Anycast)
+                // workchain_id:int8
+                // address:bits256  = MsgAddressInt;
+                maybe-anycast // get anycast depth, bits, slice
+                8 i@+ // get workchain
+                256 parse-address-with-anycast
+                `addr-std swap
+            }
+
+            {
+                // if addr_var$11
+                // anycast:(Maybe Anycast)
+                // addr_len:(## 9)
+                // workchain_id:int32
+                // address:(bits addr_len) = MsgAddressInt;
+                maybe-anycast // get anycast depth, bits, slice
+                9 u@+  // get addr_len
+                32 i@+ // get workchain
+                swap 2 -roll // move workchain to neede position
+                swap parse-address-with-anycast
+                `addr-var swap
+            } cond
+
+       }
+       {
+            drop // drop header (dup for statment upper)
+            // if addr_extern$01
+            // addr_extern$01 len:(## 9)
+            // external_address:(bits len)
+            9 u@+ swap  // bit len
+            u@+ // external_address
+            `addr-extern swap
+       } cond
+    }
+    {
+        swap
+        // if addr_none$00
+        `addr-none swap
+    } cond
+} : addr@+
+
+{ addr@+ drop } : addr@
+
+// User-friendly prints output of addr@
+// (0 A or addr A or wc addr A -- )
+{
+    dup `addr-none eq?
+    { 2drop ."addr_none" }
+    {
+        `addr-extern eq?
+        { (dump) type }
+        { (x.) swap (dump) ":" $+ swap $+ type }
+        cond
+    }
+    cond
+} : print-addr // print addr with workchain
+
+forget maybe-anycast
+forget parse-address-with-anycast
\ No newline at end of file
diff --git a/src/toncli/lib/func-libs/stdlib.func b/src/toncli/lib/func-libs/stdlib.func
new file mode 100644
index 0000000..0431d32
--- /dev/null
+++ b/src/toncli/lib/func-libs/stdlib.func
@@ -0,0 +1,211 @@
+;; Standard library for funC
+;;
+
+forall X -> tuple cons(X head, tuple tail) asm "CONS";
+forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
+forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
+forall X -> X car(tuple list) asm "CAR";
+tuple cdr(tuple list) asm "CDR";
+tuple empty_tuple() asm "NIL";
+forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
+forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
+forall X -> [X] single(X x) asm "SINGLE";
+forall X -> X unsingle([X] t) asm "UNSINGLE";
+forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
+forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
+forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
+forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
+forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
+forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
+forall X -> X first(tuple t) asm "FIRST";
+forall X -> X second(tuple t) asm "SECOND";
+forall X -> X third(tuple t) asm "THIRD";
+forall X -> X fourth(tuple t) asm "3 INDEX";
+forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
+forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
+forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
+forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
+forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
+forall X -> X null() asm "PUSHNULL";
+forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP";
+
+int now() asm "NOW";
+slice my_address() asm "MYADDR";
+[int, cell] get_balance() asm "BALANCE";
+int cur_lt() asm "LTIME";
+int block_lt() asm "BLOCKLT";
+
+int cell_hash(cell c) asm "HASHCU";
+int slice_hash(slice s) asm "HASHSU";
+int string_hash(slice s) asm "SHA256U";
+
+int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
+int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
+
+(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
+(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
+(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
+(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
+
+;; () throw_if(int excno, int cond) impure asm "THROWARGIF";
+
+() dump_stack() impure asm "DUMPSTK";
+
+cell get_data() asm "c4 PUSH";
+() set_data(cell c) impure asm "c4 POP";
+cont get_c3() impure asm "c3 PUSH";
+() set_c3(cont c) impure asm "c3 POP";
+cont bless(slice s) impure asm "BLESS";
+
+() accept_message() impure asm "ACCEPT";
+() set_gas_limit(int limit) impure asm "SETGASLIMIT";
+() commit() impure asm "COMMIT";
+() buy_gas(int gram) impure asm "BUYGAS";
+
+int min(int x, int y) asm "MIN";
+int max(int x, int y) asm "MAX";
+(int, int) minmax(int x, int y) asm "MINMAX";
+int abs(int x) asm "ABS";
+
+slice begin_parse(cell c) asm "CTOS";
+() end_parse(slice s) impure asm "ENDS";
+(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF";
+cell preload_ref(slice s) asm "PLDREF";
+;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX";
+;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX";
+;; int preload_int(slice s, int len) asm "PLDIX";
+;; int preload_uint(slice s, int len) asm "PLDUX";
+;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";
+;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
+(slice, int) load_grams(slice s) asm( -> 1 0) "LDGRAMS";
+slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
+(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
+slice first_bits(slice s, int len) asm "SDCUTFIRST";
+slice skip_last_bits(slice s, int len) asm "SDSKIPLAST";
+(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST";
+slice slice_last(slice s, int len) asm "SDCUTLAST";
+(slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT";
+cell preload_dict(slice s) asm "PLDDICT";
+slice skip_dict(slice s) asm "SKIPDICT";
+
+(slice, cell) load_maybe_ref(slice s) asm( -> 1 0) "LDOPTREF";
+cell preload_maybe_ref(slice s) asm "PLDOPTREF";
+builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF";
+
+int cell_depth(cell c) asm "CDEPTH";
+
+int slice_refs(slice s) asm "SREFS";
+int slice_bits(slice s) asm "SBITS";
+(int, int) slice_bits_refs(slice s) asm "SBITREFS";
+int slice_empty?(slice s) asm "SEMPTY";
+int slice_data_empty?(slice s) asm "SDEMPTY";
+int slice_refs_empty?(slice s) asm "SREMPTY";
+int slice_depth(slice s) asm "SDEPTH";
+
+int builder_refs(builder b) asm "BREFS";
+int builder_bits(builder b) asm "BBITS";
+int builder_depth(builder b) asm "BDEPTH";
+
+builder begin_cell() asm "NEWC";
+cell end_cell(builder b) asm "ENDC";
+builder store_ref(builder b, cell c) asm(c b) "STREF";
+;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
+;; builder store_int(builder b, int x, int len) asm(x b len) "STIX";
+builder store_slice(builder b, slice s) asm "STSLICER";
+builder store_grams(builder b, int x) asm "STGRAMS";
+builder store_dict(builder b, cell c) asm(c b) "STDICT";
+
+(slice, slice) load_msg_addr(slice s) asm( -> 1 0) "LDMSGADDR";
+tuple parse_addr(slice s) asm "PARSEMSGADDR";
+(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR";
+(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR";
+
+cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
+(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
+cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
+(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
+cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF";
+(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF";
+(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF";
+(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF";
+(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF";
+(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL";
+(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL";
+(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
+(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT";
+(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
+(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
+(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
+(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
+cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
+(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
+cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
+(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
+cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
+(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
+(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD";
+(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE";
+(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD";
+(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE";
+cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
+(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
+cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
+(cell, ()) ~idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
+cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
+(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
+(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB";
+(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB";
+(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB";
+(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB";
+(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
+(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
+(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
+(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
+(cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
+(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
+(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
+(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
+(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
+(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
+(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
+(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
+(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
+(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAX" "NULLSWAPIFNOT2";
+(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2";
+(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2";
+(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
+(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAX" "NULLSWAPIFNOT2";
+(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2";
+(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2";
+(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
+(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2";
+(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2";
+(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2";
+(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT2";
+(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2";
+(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT2";
+(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2";
+cell new_dict() asm "NEWDICT";
+int dict_empty?(cell c) asm "DICTEMPTY";
+
+(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTGETQ" "NULLSWAPIFNOT2";
+(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) "PFXDICTSET";
+(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTDEL";
+
+cell config_param(int x) asm "CONFIGOPTPARAM";
+int cell_null?(cell c) asm "ISNULL";
+
+() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
+() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX";
+() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG";
+() set_code(cell new_code) impure asm "SETCODE";
+
+int random() impure asm "RANDU256";
+int rand(int range) impure asm "RAND";
+int get_seed() impure asm "RANDSEED";
+int set_seed() impure asm "SETRAND";
+() randomize(int x) impure asm "ADDRAND";
+() randomize_lt() impure asm "LTIME" "ADDRAND";
+
+builder store_coins(builder b, int x) asm "STVARUINT16";
+(slice, int) load_coins(slice s) asm( -> 1 0) "LDVARUINT16";
\ No newline at end of file
diff --git a/src/toncli/main.py b/src/toncli/main.py
index 9f417b9..294aba6 100644
--- a/src/toncli/main.py
+++ b/src/toncli/main.py
@@ -1,20 +1,33 @@
 import argparse
+import shutil
 import sys
 import textwrap
+import shlex
+
+import configparser
 import pkg_resources
 import requests
 
+import os.path
+
+from appdirs import user_config_dir
+
 from colorama import Fore, Style
 
 from toncli.modules.deploy_contract import ContractDeployer
 from toncli.modules.projects import ProjectBootstrapper
+from toncli.modules.tests.tests import TestsRunner
 from toncli.modules.utils.func.func import Func
 from toncli.modules.utils.system.argparse_fix import argv_fix
+from toncli.modules.utils.system.conf import config_file, getcwd
 from toncli.modules.utils.system.log import logger
 from toncli.modules.utils.fift.cli_lib import process_build_cli_lib_command
 from toncli.modules.utils.fift.fift import Fift
 from toncli.modules.utils.lite_client.lite_client import LiteClient
 from toncli.modules.utils.transaction import run_transaction
+from toncli.modules.utils.check_hash import check_2_libs_actual, get_libs_paths
+from toncli.modules.abstract.deployer import AbstractDeployer
+from toncli.modules.deploy_wallet_contract import DeployWalletContract
 
 gr = Fore.GREEN
 bl = Fore.CYAN
@@ -27,6 +40,7 @@ def main():
 
     :return:
     '''
+
     fift_help = f'''positional arguments:
       {bl}command{rs}              Which mode to run, can be [interactive, run, sendboc]
       {gr}   interactive - default, run interactive fift
@@ -82,6 +96,13 @@ def main():
 
 {bl}tointeger - parse string to integer to pass to contract in func
 
+{bl}sendboc - send file with boc info
+{gr}   "sendboc <path-to-file.boc>" - sends BOC file
+{gr}   "sendboc <path-to=file.fif> <other-params>" -  run fift file and run sendfile in lite-client (just like command "fift sendboc ...")
+
+{bl}wallet - print addresses of 2 wallets - bounceable wallet and deploy wallet
+{gr}   You can use this command only when wallet is built with commands "toncli build" or "toncli deploy"
+
 All commands can be found in https://github.com/disintar/toncli/blob/master/docs/commands.md
 
 {rs}
@@ -103,14 +124,28 @@ def main():
     parser.add_argument("-v", "--version", help="package version", action='store_true')
     subparser = parser.add_subparsers()
 
-    version_local = pkg_resources.get_distribution("toncli").version
-    try:
-        version_global = requests.get('https://pypi.org/pypi/toncli/json').json()['info']['version']
-
-        if version_global and version_global != version_local:
-            print(update_text)
-    except:
-        pass
+    # version_local = pkg_resources.get_distribution("toncli").version
+    # try:
+    #     version_global = requests.get('https://pypi.org/pypi/toncli/json').json()['info']['version']
+    #
+    #     if version_global and version_global != version_local:
+    #         logger.info(update_text)
+    # except:
+    #     pass
+
+    config = configparser.ConfigParser()
+    config.read(config_file)
+    config_default = config['DEFAULT']
+
+    warn = config_default.get('LIBS_WARNING') != 'False'
+
+    if warn:
+        if not check_2_libs_actual():
+            local_lib_path, global_lib_path = get_libs_paths()
+            logger.warning(
+                f"""\nIts seems that your local fift and func libs ({local_lib_path}) differs from their actual versions ({global_lib_path}). 
+You can update them automatically using "toncli update_libs" or disable this warning by changing "LIBS_WARNING" to "False" param in cofig\n\n"""
+            )
     #
     # START
     #
@@ -127,26 +162,49 @@ def main():
     #
 
     parser_deploy = subparser.add_parser('deploy', description='Deploy project to blockchain')
-    parser_deploy.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet'],
+    parser_deploy.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet', 'ownnet'],
                                help='Network to deploy')
     parser_deploy.add_argument("--workchain", "-wc", default=0, type=int, help='Workchain deploy to')
     parser_deploy.add_argument("--ton", "-t", default=0.05, type=float,
                                help='How much TON will be sent to new contract')
     parser_deploy.add_argument("--update", action='store_true', help='Update cached configs of net')
+    parser_deploy.add_argument('--data-params', help='Data which you want to pass to data of your smart-contract',
+                               default="", type=str)
 
     #
     # get
     #
 
     parser_get = subparser.add_parser('get', description='Deploy project to blockchain')
-    parser_get.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet'],
+    parser_get.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet', 'ownnet'],
                             help='Network to deploy')
     parser_get.add_argument("--update", action='store_true', help='Update cached configs of net')
     parser_get.add_argument("--contracts", "-c", type=str,
                             help='Set contract name from project.yaml to run getmethod on')
+    parser_get.add_argument("--address", "-a", type=str,
+                            help='Set contract address to run get method on')
     parser_get.add_argument("--fift", "-f", type=str,
                             help='Run fift script on get output. Get output will be loaded to stack')
 
+    #
+    # send
+    #
+
+    parser_send = subparser.add_parser('send', description='Send internal transaction from deploy wallet to smc')
+    parser_send.add_argument("--amount", "-a", type=float, default=0, help='How much TON need to send')
+    parser_send.add_argument("--contracts", "-c", type=str, help='Set contract name from project.yaml to send to')
+    parser_send.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet', 'ownnet'],
+                             help='Network to use')
+    parser_send.add_argument("--update", action='store_true', help='Update cached configs of net')
+    parser_send.add_argument("--address", type=str,
+                             help='Set contract address to run get method on')
+
+    parser_send.add_argument("--mode", type=int, help='Sets transfer mode (0..255) for SENDRAWMSG')
+    parser_send.add_argument("--body", "-b", type=str,
+                             help='Path to fift file to get body from (need to set cell in the end of stack)')
+    parser_send.add_argument("--no-bounce", "-nb", type=int, help='Clears bounce flag')
+    parser_send.add_argument("--force-bounce", "-fb", type=int, help='Forces bounce flag')
+
     #
     # tointeger
     #
@@ -163,7 +221,8 @@ def main():
     parser_run_transaction.add_argument("logical_time", type=str)
     parser_run_transaction.add_argument("transaction_hash", type=str)
     parser_run_transaction.add_argument("smc_address", type=str)
-    parser_run_transaction.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet'],
+    parser_run_transaction.add_argument("--net", "-n", default='testnet', type=str,
+                                        choices=['testnet', 'mainnet', 'ownnet'],
                                         help='Network to run transaction')
     parser_run_transaction.add_argument("--function", "-f", default=-1, type=int,
                                         help='Function selector on runvm (-1 - external message, 0 - internal, ...')
@@ -197,7 +256,7 @@ def main():
     parser_fift = subparser.add_parser('fift', help=fift_help,
                                        formatter_class=argparse.RawDescriptionHelpFormatter,
                                        description=textwrap.dedent(fift_help))
-    parser_fift.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet'],
+    parser_fift.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet', 'ownnet'],
                              help='Network to deploy')
     parser_fift.add_argument("--workchain", "-wc", default=0, type=int, help='Workchain deploy to')
     parser_fift.add_argument("--update", action='store_true', default=False, help='Update cached configs of net')
@@ -220,7 +279,8 @@ def main():
     parser_lite_client = subparser.add_parser('lite-client', help=lite_client_help,
                                               formatter_class=argparse.RawDescriptionHelpFormatter,
                                               description=textwrap.dedent(lite_client_help))
-    parser_lite_client.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet'],
+    parser_lite_client.add_argument("--net", "-n", default='testnet', type=str,
+                                    choices=['testnet', 'mainnet', 'ownnet'],
                                     help='Network to deploy')
     parser_lite_client.add_argument("--update", action='store_true', default=False, help='Update cached configs of net')
     parser_lite_client.add_argument("--lite-client-args", "-la", type=str,
@@ -230,6 +290,33 @@ def main():
                                     default='',
                                     help='Pass args to lite-client command at the end')
 
+    #
+    #  SEND BOC
+    #
+    parser_sendboc = subparser.add_parser('sendboc')
+    parser_sendboc.add_argument('file', type=argparse.FileType('r'))
+    parser_sendboc.add_argument("--net", "-n", default='testnet', type=str, choices=['testnet', 'mainnet', 'ownnet'],
+                                help='Network to deploy')
+
+    #
+    #  WALLET
+    #
+    wallet = subparser.add_parser('wallet')
+
+    #
+    #  TESTS
+    #
+    run_tests = subparser.add_parser('run_tests')
+    run_tests.add_argument("--contracts", "-c", type=str,
+                           help='Set contract name from project.yaml to run tests on')
+    run_tests.add_argument("--verbose", "-v", type=int, default=0,
+                           help='Set contract name from project.yaml to run tests on')
+
+    #
+    #  UPDATE LIBS
+    #
+    parser_update_libs = subparser.add_parser('update_libs')
+
     #
     #  FUNC
     #
@@ -277,6 +364,9 @@ def main():
     elif command in ['lite-client', 'lc']:
         _, kwargs = argv_fix(sys.argv, string_kwargs)
         args = parser.parse_args(['lite-client', *kwargs])
+    elif command == 'sendboc':
+        args, kwargs = argv_fix(sys.argv, string_kwargs)
+        args = parser.parse_args(['sendboc', args[2], *kwargs])
     elif command in ['func', 'fc', 'build']:
         _, kwargs = argv_fix(sys.argv, string_kwargs)
         args = parser.parse_args(['func', *kwargs])
@@ -286,6 +376,22 @@ def main():
     elif command == 'get':
         _, kwargs = argv_fix(sys.argv, string_kwargs)
         args = parser.parse_args(['get', *kwargs])
+    elif command == 'run_tests':
+        _, kwargs = argv_fix(sys.argv, string_kwargs)
+        args = parser.parse_args(['run_tests', *kwargs])
+    elif command == 'addrs':
+        if 'project.yaml' not in os.listdir(getcwd()):
+            logger.error(f"🚫 {gr}{getcwd()}{rs} is not project root, there is no file {bl}project.yaml{rs} file")
+            sys.exit(0)
+
+        contract = ContractDeployer(network='testnet')
+        addrs = contract.get_address()
+
+        for name, addr in zip(contract.project_config.contracts, addrs):
+            logger.info(f"[{gr}{name.name}{rs}] 🦄 Raw address: {bl}{addr[0]}{rs}")
+            logger.info(f"[{gr}{name.name}{rs}] 🦝 Bounceable address: {bl}{addr[1]}{rs}")
+            logger.info(f"[{gr}{name.name}{rs}] 🐏 Non-bounceable address: {bl}{addr[2]}{rs}")
+        sys.exit()
     elif command == 'tointeger':
         args, _ = argv_fix(sys.argv, string_kwargs)
         string_to_encode = " ".join(args[2:])
@@ -310,22 +416,49 @@ def main():
         bootstrapper.deploy()
 
     elif command == 'deploy':
-        deployer = ContractDeployer(network=args.net, update_config=args.update, workchain=args.workchain, ton=args.ton)
+        deployer = ContractDeployer(network=args.net, update_config=args.update, workchain=args.workchain, ton=args.ton,
+                                    data_params=shlex.split(args.data_params))
         real_args, _ = argv_fix(sys.argv, string_kwargs)
-
         deployer.publish(real_args[2:])
 
     elif command == 'get':
-        deployer = ContractDeployer(network=args.net, update_config=args.update)
+
+        real_args, kwargs = argv_fix(sys.argv, string_kwargs)
+
+        if args.address:
+            class My:
+                name = 'my-cool-smc'
+
+            deployer = AbstractDeployer()
+            deployer.network = args.net
+            deployer.update_config = args.update
+
+            deployer.get(real_args[2:], args, fake_addreses=[[My()], [[None, args.address]]])
+        else:
+            deployer = ContractDeployer(network=args.net, update_config=args.update)
+            deployer.get(real_args[2:], args)
+    elif command == 'send':
         real_args, kwargs = argv_fix(sys.argv, string_kwargs)
-        deployer.get(real_args[2:], args)
 
+        if args.address:
+            class My:
+                name = 'my-cool-smc'
+
+            deployer = AbstractDeployer()
+            deployer.network = args.net
+            deployer.update_config = args.update
+            deployer.deploy_contract = DeployWalletContract(args.net, 0)
+
+            deployer.send([], args, fake_addreses=[[My()], [[None, args.address]]])
+        else:
+            deployer = ContractDeployer(network=args.net, update_config=args.update)
+            deployer.send([], args)
     elif command == 'run_transaction':
         run_transaction(args.net, args.smc_address, args.logical_time, args.transaction_hash, args.function, args.save)
         sys.exit()
 
     elif command == '-v':
-        print(f'v{version_local}')
+        logger.info(f'v{version_local}')
 
     elif command in ['fift', 'f', 'run']:
         # get real args
@@ -376,6 +509,58 @@ def main():
         # If use run command instead of f run - need to change start arg parse position
         func = Func(command, kwargs=kwargs, args=args_to_pass)
         func.run()
+    elif command == 'sendboc':
+        real_args, _ = argv_fix(sys.argv, string_kwargs)
+
+        # Parse kwargs by argparse
+        kwargs = dict(args._get_kwargs())
+
+        file = kwargs['file']
+        ext = file.name.split('.')[-1]
+        if ext == 'boc':
+            lc = LiteClient(command=f"sendfile", args=[file.name],
+                            kwargs={'net': kwargs['net'], 'update': False, 'lite_client_args': '-v 1'})
+            lc.run()
+        elif ext == 'fif':
+            fift_params = real_args[2:]
+            fift = Fift(command='sendboc', args=fift_params)
+            fift.run()
+        else:
+            logger.error('This file extension is not supported. Supported extensions are .boc and .fif')
+    elif command == 'wallet':
+        contract_addr_file_name = 'build/contract_address'
+        if os.path.isfile(contract_addr_file_name):
+            bounceable_addr = ""
+            with open(contract_addr_file_name, 'r', encoding='utf-8') as file:
+                addresses = file.read().split()
+                bounceable_addr = addresses[2]
+            logger.info(f"Your bounceable address is: {gr}{bounceable_addr}{rs}")
+
+            deploy_wallet_addr_dir = user_config_dir('toncli')
+            deploy_bouncable = ""
+            with open(os.path.abspath(f"{deploy_wallet_addr_dir}/wallet/build/contract_address"), 'r',
+                      encoding='utf-8') as file:
+                addresses = file.read().split()
+                deploy_bouncable = addresses[2]
+            logger.info(f"Your deploy wallet address is: {gr}{deploy_bouncable}{rs}")
+        else:
+            logger.error(
+                "Can't find file with address information.\n"
+                "Its seems that you haven't built your wallet yet.\n"
+                "You can do it with commands:\n"
+                "'toncli build' - to build locally\n"
+                "'toncli deploy' to build and immediately deploy it to net")
+    elif command == 'update_libs':
+        global_lib_path, local_lib_path = get_libs_paths()
+
+        shutil.copytree(os.path.abspath(f"{global_lib_path}/fift-libs"), os.path.abspath(f"{local_lib_path}/fift-libs"),
+                        dirs_exist_ok=True)
+        shutil.copytree(os.path.abspath(f"{global_lib_path}/func-libs"), os.path.abspath(f"{local_lib_path}/func-libs"),
+                        dirs_exist_ok=True)
+        logger.info(f"Succesfully copied fift and func libs\nfrom {global_lib_path}\nto {local_lib_path}")
+    elif command == 'run_tests':
+        test_runner = TestsRunner()
+        test_runner.run(args.contracts, verbose=args.verbose)
     else:
         logger.error("🔎 Can't find such command")
         sys.exit()
diff --git a/src/toncli/modules/abstract/deployer.py b/src/toncli/modules/abstract/deployer.py
index 9b5d00d..24defd7 100644
--- a/src/toncli/modules/abstract/deployer.py
+++ b/src/toncli/modules/abstract/deployer.py
@@ -1,25 +1,45 @@
 import os
 import sys
-from itertools import cycle
-from time import sleep
-from typing import Tuple, Optional, List
+import tempfile
+from argparse import Namespace
+from typing import List
 
 from colorama import Fore, Style
+from itertools import cycle
+from time import sleep
+from typing import Tuple
 
-from toncli.modules.utils.system.conf import project_root
 from toncli.modules.utils.fift.commands import contract_manipulation, test_fift
 from toncli.modules.utils.func.commands import build as fift_build
 from toncli.modules.utils.lite_client.commands import get_account_status, send_boc
 from toncli.modules.utils.system.project import check_for_needed_files_to_deploy
-from toncli.modules.utils.lite_client.lite_client import LiteClient
+from toncli.modules.utils.system.project_conf import TonProjectConfig
 from toncli.modules.utils.system.log import logger
-from toncli.modules.utils.system.project_conf import ProjectConf, TonProjectConfig
+from toncli.modules.utils.fift.fift import Fift
+from toncli.modules.utils.system.project_conf import ProjectConf
+from toncli.modules.utils.ton.cell import deserialize
+from toncli.modules.utils.lite_client.parser import split_get_output
+from jinja2 import FileSystemLoader, Environment, select_autoescape
+
+from toncli.modules.utils.lite_client.lite_client import LiteClient
+from toncli.modules.utils.system.conf import project_root, getcwd
 
 bl = Fore.CYAN
 gr = Fore.GREEN
 rs = Style.RESET_ALL
 
 
+class Cell:
+    def __init__(self, data: str, refs: List['Cell']):
+        self.data = data
+        self.refs = refs
+
+    def serialize(self):
+        refs = [cell.serialize() for cell in self.refs]
+        refs = [f"{ref} ref," for ref in refs]
+        return f"<b {self.data} s, {' '.join(refs)} b>"
+
+
 class AbstractDeployer:
     def __init__(self):
         self.update_config: bool = False
@@ -28,6 +48,21 @@ def __init__(self):
         self.workchain: int = 0
         self.project_root: str = ""
         self.project_config: ProjectConf = ...
+        self.data_params: list = []
+
+    def parse_contracts(self, kwargs):
+        contracts = kwargs.contracts.split() if kwargs.contracts else None
+        if contracts is not None and len(contracts) > 0:
+            real_contracts = []
+
+            for item in contracts:
+                for config in self.project_config.contracts:
+                    if config.name == item:
+                        real_contracts.append(config)
+        else:
+            real_contracts = self.project_config.contracts
+
+        return real_contracts
 
     def get_status(self, addreses: List[List[str]] = None) -> List[Tuple[float, bool]]:
         """Get balance and inited state for Contract"""
@@ -51,7 +86,7 @@ def deploy(self, contracts: List[TonProjectConfig] = None):
 
         for contract, (_, is_inited) in zip(contracts, statuses):
             if not is_inited:
-                deploy_boc = send_boc(self.network, contract.boc, cwd=self.project_root,
+                deploy_boc = send_boc(self.network, os.path.abspath(contract.boc), cwd=os.path.abspath(self.project_root),
                                       update_config=self.update_config, get_output=True)
 
                 if 'error' in deploy_boc:
@@ -69,12 +104,13 @@ def build(self, contracts: List[TonProjectConfig] = None):
 
         data = []
         for contract in contracts:
-            data.append(contract_manipulation(contract.to_save_location,
-                                  contract.data,
-                                  self.workchain,
-                                  contract.boc,
-                                  contract.address,
-                                  cwd=self.project_root))
+            data.append(contract_manipulation(os.path.abspath(contract.to_save_location),
+                                              os.path.abspath(contract.data),
+                                              self.workchain,
+                                              os.path.abspath(contract.boc),
+                                              os.path.abspath(contract.address),
+                                              cwd=self.project_root,
+                                              data_params=self.data_params))
         return data
 
     def get_address(self, contracts: List[TonProjectConfig] = None) -> List[List[str]]:
@@ -86,10 +122,10 @@ def get_address(self, contracts: List[TonProjectConfig] = None) -> List[List[str
 
         for contract in contracts:
             # TODO: load address from build/contract.addr
-            if not os.path.exists(contract.address):
+            if not os.path.exists(os.path.abspath(contract.address)):
                 raise ValueError(f"😥 No address_text found in {contract.address}")
 
-            with open(contract.address) as f:
+            with open(os.path.abspath(contract.address), encoding='utf-8') as f:
                 address_text = f.read().split()
 
                 if len(address_text) != 3:
@@ -110,9 +146,9 @@ def run_tests(self, contracts: List[TonProjectConfig] = None):
         for contract in contracts:
             # Run tests
             # CWD - Need to specify folder so keys saved to build/ (relative path in fift)
-            test_fift(fift_files_locations=[contract.data],
-                      test_file_path=f"{project_root}/modules/fift/run_test.fif",
-                      cwd=self.project_root)
+            test_fift(fift_files_locations=[os.path.abspath(contract.data)],
+                      test_file_path=f"fift_tests.fif.template.fif",
+                      cwd=self.project_root, data_params=self.data_params)
 
     def check_for_needed_files_to_deploy(self) -> bool:
         """Check if current root is project root"""
@@ -166,7 +202,7 @@ def wait_for_deploy(self, contracts: List[TonProjectConfig] = None, only_balance
 
     def get_seqno(self) -> List[int]:
         """Run runmethod on lite-client and parse seqno from answer"""
-
+        logger.info("🐰 Getting seqno for transaction")
         seqnos = []
         for address in self.addresses:
             lite_client = LiteClient('runmethod', args=[address[1], 'seqno'], kwargs={'lite_client_args': '-v 0',
@@ -180,3 +216,191 @@ def get_seqno(self) -> List[int]:
             seqnos.append(output)
 
         return seqnos
+
+    def send(self, args: List[str], kwargs: Namespace, fake_addreses=False):
+        if not fake_addreses:
+            real_contracts = self.parse_contracts(kwargs)
+        else:
+            real_contracts = fake_addreses[0]
+
+        names = ', '.join([i.name for i in real_contracts])
+
+        logger.info(
+            f"🤔 You want to send internal message to [{gr}{names}{rs}] from deploy-wallet"
+            f" with amount [{bl}{kwargs.amount}{rs}]")
+
+        balance, is_inited = self.deploy_contract.get_status()[0]
+
+        if balance < kwargs.amount or not is_inited:
+            logger.error(
+                f"💰 Please, send more TON for deployment to [{gr}{self.deploy_contract.addresses[0][1]}{rs}] in"
+                f" [{bl}{self.deploy_contract.network}{rs}]")
+            sys.exit()
+
+        if not fake_addreses:
+            # Get contracts addresses
+            self.addresses = self.get_address(real_contracts)
+        else:
+            self.addresses = fake_addreses[1]
+
+        for address in self.addresses:
+            seqno = self.deploy_contract.get_seqno()[0]
+            args = [f'{self.deploy_contract.project_root}/fift/usage.fif', 'build/contract', address[1], '0',
+                    str(seqno),
+                    str(kwargs.amount)]
+
+            if kwargs.body:
+                if kwargs.body[0] != '/':  # not absolute path
+                    args.extend(['-B', f"{getcwd()}/{kwargs.body}"])
+                else:  # use absolute path
+                    args.extend(['-B', f"{kwargs.body}"])
+
+            if kwargs.force_bounce:
+                args.append('--force-bounce')
+
+            if kwargs.no_bounce:
+                args.append('--no-bounce')
+
+            if kwargs.mode:
+                args.extend(['--mode', kwargs.mode])
+
+            logger.info(f"Run command: {' '.join(args)}")
+
+            fift = Fift('sendboc', args=args, kwargs={'fift_args': "",
+                                                      'lite_client_args': "",
+                                                      'build': False,
+                                                      'net': self.network,
+                                                      'update': False}, quiet=False,
+                        cwd=self.deploy_contract.project_root)
+            fift.run()
+
+    def get(self, args: List[str], kwargs: Namespace, fake_addreses=False):
+        """Run get methods on contracts"""
+        # TODO: it wasn't good idea to parse lite client output
+        # We can run get methods locally by runvm (savedata / saveaccount) and then get output / run fift
+        # It's needed to be done this way
+
+        if not fake_addreses:
+            real_contracts = self.parse_contracts(kwargs)
+
+            # Get contracts addresses
+            self.addresses = self.get_address(real_contracts)
+        else:
+            real_contracts, self.addresses = fake_addreses
+
+        for address, contract in zip(self.addresses, real_contracts):
+            logger.info(f"👯 [{bl}{contract.name}{rs}] [{gr}{address[1]}{rs}] runmethod {args}")
+            lite_client = LiteClient('runmethod', args=[address[1], *args], kwargs={'lite_client_args': '-v 0',
+                                                                                    'net': self.network,
+                                                                                    'update': self.update_config},
+                                     get_output=True)
+            output = lite_client.run_safe()
+            output = output.split('\n')[-3]
+            output = output[11:-2]
+            logger.info(f"🧐 Output: [ {output} ]")
+            if kwargs.fift and len(kwargs.fift) > 0:
+                output = split_get_output(output)
+                to_fift = []
+
+                # TODO: use fift runvm
+                # This is not right, but we have not time
+                # This code is load C{...} from lite client to fift code
+                for line in output:
+                    # If cell hash present
+                    if line[:2] == 'C{':
+                        _hash = line[2:-1]
+
+                        # we need to parse cell
+                        lite_client = LiteClient('runmethod', args=[address[1], *args],
+                                                 kwargs={'lite_client_args': '-v 0',
+                                                         'net': self.network,
+                                                         'update': self.update_config,
+                                                         'lite_client_post_args': ["-c", f"dumpcell {_hash}"]},
+                                                 get_output=True)
+                        output_cells = lite_client.run_safe()
+
+                        cells = []
+
+                        append_other = False
+                        # cell can contains references
+                        for line in output_cells.split('\n'):
+                            if append_other and len(line):
+                                cells.append(line[2:])
+
+                            if _hash.upper() in line and '} =' in line:
+                                append_other = True
+
+                        main_cell = None
+                        for cell in cells:
+                            level = len(cell) - len(cell.strip())
+
+                            if level == 0:
+                                main_cell = Cell(data=cell, refs=[])
+                            else:
+                                needed_cell: Cell = None
+
+                                for current_level in range(level):
+                                    if not needed_cell:
+                                        needed_cell = main_cell
+                                    else:
+                                        needed_cell = needed_cell.refs[-1]
+
+                                needed_cell.refs.append(Cell(data=cell.strip(), refs=[]))
+                        to_fift.append(main_cell.serialize())
+                    elif line[:3] == 'CS{':
+                        # Дай бог здоровья больше не писать такой код
+                        # И использовать fift runvm
+                        # Но к несчастью я не догадался так сделать сначала
+                        # А сейчас хочется сделать продакшн реди как можно быстрее
+                        # Если кто-то это переделает - буду очень благодарен
+                        # disintar.io
+
+                        cell = line.split()[0].replace('CS{Cell{', '')[:-1]
+
+                        cut = list(map(int, line.split()[2][:-1].split('..')))
+
+                        bits = deserialize(cell, *cut)
+
+                        bits = ["<b b{%s} s, b> <s" % bits[i:i + 128] for i in range(0, len(bits), 128)]
+                        if len(bits) > 1:
+                            bits = f'{bits[0]} {" |+ ".join(bits[1:])} |+'
+                        else:
+                            bits = bits[0]
+
+                        to_fift.append(bits)
+                    else:
+                        to_fift.append(line)
+
+                render_kwargs = {
+                    'code': kwargs.fift,
+                    'output': ' '.join(to_fift)
+                }
+
+                # Load template of transaction_debug
+                loader = FileSystemLoader(f"{project_root}/modules/fift")
+
+                env = Environment(
+                    loader=loader,
+                    autoescape=select_autoescape()
+                )
+
+                template = env.get_template("get_run.fif.template")
+
+                rendered = template.render(**render_kwargs)
+
+                temp_location: str = tempfile.mkstemp(suffix='.fif')[1]
+
+                with open(temp_location, 'w', encoding='utf-8') as f:
+                    f.write(rendered)
+
+                fift = Fift('run', args=[temp_location])
+                fift.run()
+            else:
+                try:
+                    output = int(output)
+                    hex = "{0:x}".format(output)
+
+                    string_output = bytearray.fromhex(hex).decode()
+                    logger.info(f"🧐 Auto parse string: [ {string_output} ]")
+                except Exception as e:
+                    logger.error(f"🧐 Can't auto parse string")
diff --git a/src/toncli/modules/deploy_contract.py b/src/toncli/modules/deploy_contract.py
index 9773033..0759518 100644
--- a/src/toncli/modules/deploy_contract.py
+++ b/src/toncli/modules/deploy_contract.py
@@ -1,48 +1,32 @@
 import os
 import sys
-import tempfile
-from argparse import Namespace
 from typing import List
 
 from colorama import Fore, Style
 
 from toncli.modules.abstract.deployer import AbstractDeployer
 from toncli.modules.deploy_wallet_contract import DeployWalletContract
+from toncli.modules.utils.system.conf import getcwd
 from toncli.modules.utils.system.log import logger
-from toncli.modules.utils.fift.fift import Fift
 from toncli.modules.utils.system.project import migrate_project_struction
 from toncli.modules.utils.system.project_conf import ProjectConf
-from jinja2 import FileSystemLoader, Environment, select_autoescape
-
-from toncli.modules.utils.lite_client.lite_client import LiteClient
-from toncli.modules.utils.system.conf import project_root
 
 gr = Fore.GREEN
 bl = Fore.CYAN
 rs = Style.RESET_ALL
 
 
-class Cell:
-    def __init__(self, data: str, refs: List['Cell']):
-        self.data = data
-        self.refs = refs
-
-    def serialize(self):
-        refs = [cell.serialize() for cell in self.refs]
-        refs = [f"{ref} ref," for ref in refs]
-        return f"<b {self.data} s, {' '.join(refs)} b>"
-
-
 class ContractDeployer(AbstractDeployer):
-    def __init__(self, network: str, update_config: bool = False, workchain: int = 0, ton: int = 0.05):
+    def __init__(self, network: str, update_config: bool = False, workchain: int = 0, ton: int = 0.05,
+                 data_params: list = []):
         super().__init__()
 
         self.network: str = network
         self.update_config: bool = update_config
-        self.project_root: str = os.getcwd()
+        self.project_root: str = getcwd()
 
         # If files.yaml in func folder - it's older version of project structure, so migrate
-        if os.path.exists(f"{self.project_root}/func/files.yaml"):
+        if os.path.exists(os.path.abspath(f"{self.project_root}/func/files.yaml")):
             migrate_project_struction('0.0.14', self.project_root)
 
         self.project_config = ProjectConf(self.project_root)
@@ -51,6 +35,8 @@ def __init__(self, network: str, update_config: bool = False, workchain: int = 0
         self.ton = ton  # ton to send to smart contract
         self.workchain = workchain  # workchain deploy to
 
+        self.data_params = data_params if len(data_params) else [""]  # data which yuo want to store in nft
+
         # Check needed to deploy files
         self.check_for_needed_files_to_deploy()
 
@@ -72,118 +58,6 @@ def __init__(self, network: str, update_config: bool = False, workchain: int = 0
                     "🧓 Deployer contract is not inited yet, please send some TON there and then I can deploy project")
                 sys.exit()
 
-    def get(self, args: List[str], kwargs: Namespace):
-        """Run get methods on contracts"""
-        contracts = kwargs.contracts.split() if kwargs.contracts else None
-        if contracts is not None and len(contracts) > 0:
-            real_contracts = []
-
-            for item in contracts:
-                for config in self.project_config.contracts:
-                    if config.name == item:
-                        real_contracts.append(config)
-        else:
-            real_contracts = self.project_config.contracts
-
-        # Get contracts addresses
-        self.addresses = self.get_address(real_contracts)
-
-        for address, contract in zip(self.addresses, real_contracts):
-            logger.info(f"👯 [{bl}{contract.name}{rs}] [{gr}{address[1]}{rs}] runmethod {args}")
-            lite_client = LiteClient('runmethod', args=[address[1], *args], kwargs={'lite_client_args': '-v 0',
-                                                                                    'net': self.network,
-                                                                                    'update': self.update_config},
-                                     get_output=True)
-            output = lite_client.run_safe()
-            output = output.split('\n')[-3]
-            output = output[11:-2]
-            logger.info(f"🧐 Output: [ {output} ]")
-
-            if kwargs.fift and len(kwargs.fift) > 0:
-                output = output.split(' ')
-                to_fift = []
-
-                # TODO: use libtonlibjson.so
-                # This is not right, but we have not time
-                # This code is load C{...} from lite client to fift code
-                for line in output:
-                    # If cell hash present
-                    if line[:2] == 'C{':
-                        _hash = line[2:-1]
-                        # we need to parse cell
-                        lite_client = LiteClient('runmethod', args=[address[1], *args],
-                                                 kwargs={'lite_client_args': '-v 0',
-                                                         'net': self.network,
-                                                         'update': self.update_config,
-                                                         'lite_client_post_args': ["-c", f"dumpcell {_hash}"]},
-                                                 get_output=True)
-                        output_cells = lite_client.run_safe()
-
-                        cells = []
-
-                        append_other = False
-                        # cell can contains references
-                        for line in output_cells.split('\n'):
-                            if append_other and len(line):
-                                cells.append(line[2:])
-
-                            if _hash.upper() in line and '} =' in line:
-                                append_other = True
-
-                        main_cell = None
-                        for cell in cells:
-                            level = len(cell) - len(cell.strip())
-
-                            if level == 0:
-                                main_cell = Cell(data=cell, refs=[])
-                            else:
-                                needed_cell: Cell = None
-
-                                for current_level in range(level):
-                                    if not needed_cell:
-                                        needed_cell = main_cell
-                                    else:
-                                        needed_cell = needed_cell.refs[-1]
-
-                                needed_cell.refs.append(Cell(data=cell.strip(), refs=[]))
-                        to_fift.append(main_cell.serialize())
-                    else:
-                        to_fift.append(line)
-
-                render_kwargs = {
-                    'code': kwargs.fift,
-                    'output': ' '.join(to_fift)
-                }
-
-                # Load template of transaction_debug
-                loader = FileSystemLoader(f"{project_root}/modules/fift")
-
-                env = Environment(
-                    loader=loader,
-                    autoescape=select_autoescape()
-                )
-
-                template = env.get_template("get_run.fif.template")
-
-                rendered = template.render(**render_kwargs)
-
-                temp_location: str = tempfile.mkstemp(suffix='.fif')[1]
-
-                with open(temp_location, 'w') as f:
-                    f.write(rendered)
-
-                fift = Fift('run', args=[temp_location])
-                fift.run()
-            else:
-                try:
-                    output = int(output)
-                    hex = "{0:x}".format(output)
-
-                    string_output = bytearray.fromhex(hex).decode()
-                    logger.info(f"🧐 Auto parse sting: [ {string_output} ]")
-                except Exception as e:
-                    logger.error(f"🧐 Can't auto parse string")
-
     def publish(self, contracts: List[str] = None):
         """Build, send ton, deploy contract"""
 
@@ -229,4 +103,4 @@ def publish(self, contracts: List[str] = None):
 
         logger.info(f"🚀 It may take some time to get is_inited to {gr}True{rs}")
 
-        self.wait_for_deploy(contracts=contracts)
+        self.wait_for_deploy(contracts=real_contracts)
diff --git a/src/toncli/modules/deploy_wallet_contract.py b/src/toncli/modules/deploy_wallet_contract.py
index c4970a3..37787e0 100644
--- a/src/toncli/modules/deploy_wallet_contract.py
+++ b/src/toncli/modules/deploy_wallet_contract.py
@@ -25,10 +25,10 @@ def __init__(self, network: str, workchain: int):
         super().__init__()
         self.network = network
         self.workchain = workchain
-        self.project_root = f"{config_folder}/wallet"
+        self.project_root = os.path.abspath(f"{config_folder}/wallet")
 
         # If files.yaml in func folder - it's older version of project structure, so migrate
-        if os.path.exists(f"{self.project_root}/func/files.yaml"):
+        if os.path.exists(os.path.abspath(f"{self.project_root}/func/files.yaml")):
             migrate_project_struction('0.0.14', self.project_root)
 
         # We need to check if wallet for deploying is exist
@@ -57,7 +57,7 @@ def __init__(self, network: str, workchain: int):
 
             if len(data):
                 logger.info(
-                    f"🗝 You need to send TON to {gr}Bounceable address{rs} of Deployment wallet to start work\n"
+                    f"🗝 You need to send TON to {gr}Non-bounceable address{rs} of Deployment wallet to start work\n"
                     f"💎 About {gr}2 TON{rs} will be OK for 10-12 contracts\n"
                     f"🧪 Test coins can be found in {bl}@testgiver_ton_bot{rs} / @tondev")
 
@@ -78,14 +78,18 @@ def send_ton(self, address: str, amount: float, quiet: bool = False):
 
         if balance < amount or not is_inited:
             logger.error(
-                f"💰 Please, send more TON for deployment to [{gr}{self.address}{rs}] in [{bl}{self.network}{rs}]")
+                f"💰 Please, send more TON for deployment to [{gr}{self.addresses[0][1]}{rs}] in [{bl}{self.network}{rs}]")
             sys.exit()
 
         seqno = self.get_seqno()[0]
-        args = [f'{self.project_root}/fift/usage.fif', 'build/contract', address, '0', str(seqno), str(amount),
+        args = [os.path.abspath(f'{self.project_root}/fift/usage.fif'), 'build/contract', address, '0', str(seqno), str(amount),
                 "--no-bounce"]
 
-        fift = Fift('sendboc', args, quiet=quiet, cwd=self.project_root)
+        fift = Fift('sendboc', args=args, kwargs={'fift_args': "",
+                                             'lite_client_args': "",
+                                             'build': False,
+                                             'net': self.network,
+                                             'update': False}, quiet=quiet, cwd=self.project_root)
         fift.run()
 
 
diff --git a/src/toncli/modules/fift/contract_manipulation.fif b/src/toncli/modules/fift/contract_manipulation.fif
index cbba40c..de8111f 100644
--- a/src/toncli/modules/fift/contract_manipulation.fif
+++ b/src/toncli/modules/fift/contract_manipulation.fif
@@ -27,7 +27,8 @@ $5 constant output_address
 <{ SETCP0 ACCEPT
    code-path include PUSHREF SETCODE
 }>c constant code
-data-path include constant data
+
+data-path file>B B>boc constant data
 
 // todo: add library support
 // todo: rewrite with comments
diff --git a/src/toncli/modules/fift/data_proxy.fif.template b/src/toncli/modules/fift/data_proxy.fif.template
new file mode 100644
index 0000000..c919b9b
--- /dev/null
+++ b/src/toncli/modules/fift/data_proxy.fif.template
@@ -0,0 +1,5 @@
+"{{ data_path }}" include
+
+2 boc+>B
+
+"{{ file_path }}" tuck B>file
\ No newline at end of file
diff --git a/src/toncli/modules/fift/deploy-wallet.fif b/src/toncli/modules/fift/deploy-wallet.fif
new file mode 100644
index 0000000..c4628f6
--- /dev/null
+++ b/src/toncli/modules/fift/deploy-wallet.fif
@@ -0,0 +1,79 @@
+#!/usr/bin/fift -s
+"TonUtil.fif" include
+"GetOpt.fif" include
+
+{ show-options-help 1 halt } : usage
+
+"" =: comment  // comment for simple transfers
+true =: allow-bounce
+false =: force-bounce
+3 =: send-mode  // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors
+60 =: timeout   // external message expires in 60 seconds
+variable extra-currencies
+{ extra-currencies @ cc+ extra-currencies ! } : extra-cc+!
+
+begin-options
+     " <filename-base> <dest-addr> <subwallet-id> <seqno> <amount> [-x <extra-amount>*<extra-currency-id>] [-n|-b] [-t<timeout>] [-B <body-boc>] [-C <comment>] [<savefile>]" +cr +tab
+    +"Creates a request to advanced wallet created by new-wallet-v3.fif, with private key loaded from file <filename-base>.pk "
+    +"and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)"
+    disable-digit-options generic-help-setopt
+  "n" "--no-bounce" { false =: allow-bounce } short-long-option
+    "Clears bounce flag" option-help
+  "b" "--force-bounce" { true =: force-bounce } short-long-option
+    "Forces bounce flag" option-help
+  "x" "--extra" { $>xcc extra-cc+! } short-long-option-arg
+    "Indicates the amount of extra currencies to be transfered" option-help
+  "t" "--timeout" { parse-int =: timeout } short-long-option-arg
+    "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help
+  "B" "--body" { =: body-boc-file } short-long-option-arg
+    "Sets the payload of the transfer message" option-help
+  "C" "--comment" { =: comment } short-long-option-arg
+    "Sets the comment to be sent in the transfer message" option-help
+  "m" "--mode" { parse-int =: send-mode } short-long-option-arg
+    "Sets transfer mode (0..255) for SENDRAWMSG (" send-mode (.) $+ +" by default)"
+    option-help
+  "h" "--help" { usage } short-long-option
+    "Shows a help message" option-help
+parse-options
+
+$# dup 5 < swap 6 > or ' usage if
+6 :$1..n
+
+true constant bounce
+$1 =: file-base
+$2 bounce parse-load-address force-bounce or allow-bounce and =: bounce 2=: dest_addr
+$3 parse-int =: subwallet_id
+$4 parse-int =: seqno
+$5 $>cc extra-cc+! extra-currencies @ 2=: amount
+$6 "wallet-query" replace-if-null =: savefile
+subwallet_id (.) 1 ' $+ does : +subwallet
+
+file-base +subwallet +".addr" dup file-exists? { drop file-base +".addr" } ifnot
+load-address
+2dup 2constant wallet_addr
+."INFO: 👀 Source wallet address = " 2dup 6 .Addr cr
+file-base +".pk" load-keypair nip constant wallet_pk
+
+def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond
+constant body-cell
+
+."INFO: 👋 Send " dest_addr 2dup bounce 7 + .Addr ." = "
+."subwallet_id=0x" subwallet_id x.
+."seqno=0x" seqno x. ."bounce=" bounce . cr
+."INFO: 🧟 Body of transfer message is " body-cell <s csr.
+
+// create a message
+<b b{01} s, bounce 1 i, b{000} s, dest_addr Addr, amount Gram+cc, 0 9 64 32 + + u,
+  body-cell <s 2dup 1 s-fits-with? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
+b>
+
+<b subwallet_id 32 u, now timeout + 32 u, seqno 32 u, send-mode 8 u, swap ref, b>
+
+dup hashu wallet_pk ed25519_sign_uint
+<b b{1000100} s, wallet_addr addr, 0 Gram, b{00} s,
+   swap B, swap <s s, b>
+
+2 boc+>B
+
+saveboc // it is defined in build/cli.fif (or /tmp if in script mode)
+// it is project-specific lib from tlcli thats specify needed locations
diff --git a/src/toncli/modules/fift/transaction_debug.fif.template b/src/toncli/modules/fift/transaction_debug.fif.template
index 5f1d41f..9b81660 100644
--- a/src/toncli/modules/fift/transaction_debug.fif.template
+++ b/src/toncli/modules/fift/transaction_debug.fif.template
@@ -14,7 +14,7 @@
 
 "{{ config }}" file>B B>boc constant global_config
 
-"{{ smc_address }}" true parse-load-address drop swap drop constant address
+"{{ smc_address }}" true parse-load-address drop 2constant address
 
 0x076ef1ea           // magic
 0                    // actions
@@ -24,10 +24,11 @@
 {{ trans_lt }}       // trans_lt
 239                  // randseed
 {{ amount }} null pair // balance_remaining
-address                 // myself
+<b address Addr, b> <s // myself
 global_config        // global_config
 10 tuple 1 tuple constant c7 // save as c7 cell
 
+{{ amount }}
 msg_value
 in_msg_cell
 in_msg_body
@@ -35,5 +36,5 @@ in_msg_body
 code <s // load func code as slice
 storage // add c4 cell lodaded from lite-client
 c7 // add c7 cell
-runvmctx 2drop // Runvm, in stack now seqno
-.s
+0x75 runvmx  // Runvm, in stack now seqno
+// .s
diff --git a/src/toncli/modules/projects.py b/src/toncli/modules/projects.py
index 8b5b887..820b26b 100644
--- a/src/toncli/modules/projects.py
+++ b/src/toncli/modules/projects.py
@@ -6,7 +6,7 @@
 
 from colorama import Fore, Style
 
-from toncli.modules.utils.system.conf import project_root
+from toncli.modules.utils.system.conf import project_root, getcwd
 from toncli.modules.utils.system.log import logger
 
 gr = Fore.GREEN
@@ -27,22 +27,23 @@ def __init__(self, project_name: str, folder_name: str, location: Optional[str]
 
         self.project_location = f"{project_root}/projects"
         # current location where we need to create folder with project
-        self.current_location = os.getcwd() if not location else location
+        self.current_location = getcwd() if not location else location
 
     def deploy(self) -> None:
         logger.info(
             f"🐒 I'll create folder {gr}{self.current_location}/{self.folder_name}{rs} with project "
             f"{gr}{self.project_name}{rs} and all needed files")
 
-        if not os.path.exists(f"{self.current_location}/{self.folder_name}"):
-            os.mkdir(f"{self.current_location}/{self.folder_name}")  # create new project dir
+        if not os.path.exists(os.path.abspath(f"{self.current_location}/{self.folder_name}")):
+            os.mkdir(os.path.abspath(f"{self.current_location}/{self.folder_name}"))  # create new project dir
         else:
             logger.error(
                 f"🧨 Folder {self.current_location}/{self.folder_name} already exist, please use different one "
                 f"(folder name can be defined by -n flag, e.g. -n my-wallet)")
             sys.exit()
 
-        shutil.copytree(f"{self.project_location}/{self.project_name}", f"{self.current_location}/{self.folder_name}",
+        shutil.copytree(os.path.abspath(f"{self.project_location}/{self.project_name}"),
+                        os.path.abspath(f"{self.current_location}/{self.folder_name}"),
                         dirs_exist_ok=True)  # copy all from default project to new directory
 
         logger.info(f"👑 Folder {gr}successfully {rs}created - happy blockchain hacking")
diff --git a/src/toncli/modules/utils/check_hash.py b/src/toncli/modules/utils/check_hash.py
new file mode 100644
index 0000000..90e46e1
--- /dev/null
+++ b/src/toncli/modules/utils/check_hash.py
@@ -0,0 +1,35 @@
+import glob
+import hashlib
+import os
+import pathlib
+
+from appdirs import user_config_dir
+
+from toncli.modules.utils.system.conf import project_root
+
+
+def get_dir_hashes(path):
+    ans = []
+    for path, subdirs, files in os.walk(path):
+        for name in list(sorted(files)):
+            fname = os.path.join(path, name)
+            with open(fname, 'rb', encoding='utf-8') as file:
+                data = file.read()
+                ans.append(hashlib.md5(data).hexdigest())
+    return ans
+
+
+def check_2_libs_actual():
+    global_path, local_path = get_libs_paths()
+
+    global_fift_hashes = get_dir_hashes(os.path.abspath(f"{global_path}/fift-libs"))
+    local_fift_hashes = get_dir_hashes(os.path.abspath(f"{local_path}/fift-libs"))
+
+    global_func_hashes = get_dir_hashes(os.path.abspath(f"{global_path}/func-libs"))
+    local_func_hashes = get_dir_hashes(os.path.abspath(f"{local_path}/func-libs"))
+
+    return global_fift_hashes == local_fift_hashes and global_func_hashes == local_func_hashes
+
+
+def get_libs_paths():
+    return os.path.abspath(f"{project_root}/lib"), user_config_dir('toncli')
diff --git a/src/toncli/modules/utils/fift/cli_lib.py b/src/toncli/modules/utils/fift/cli_lib.py
index 6c7e8bf..418e405 100644
--- a/src/toncli/modules/utils/fift/cli_lib.py
+++ b/src/toncli/modules/utils/fift/cli_lib.py
@@ -32,7 +32,7 @@ def build_cli_lib(to_save_location: Optional[str] = None, render_kwargs: Optiona
 
     rendered = template.render(**render_kwargs)
 
-    with open(to_save_location, 'w') as f:
+    with open(to_save_location, 'w', encoding='utf-8') as f:
         f.write(rendered)
 
     return to_save_location
diff --git a/src/toncli/modules/utils/fift/commands.py b/src/toncli/modules/utils/fift/commands.py
index e9c3892..4ded65c 100644
--- a/src/toncli/modules/utils/fift/commands.py
+++ b/src/toncli/modules/utils/fift/commands.py
@@ -1,11 +1,13 @@
 import os
 import subprocess
 import sys
+import tempfile
 from typing import List, Optional
 
 from colorama import Fore, Style
+from jinja2 import FileSystemLoader, select_autoescape, Environment
 
-from toncli.modules.utils.system.conf import config_folder, executable, project_root
+from toncli.modules.utils.system.conf import config_folder, executable, project_root, getcwd
 from toncli.modules.utils.system.log import logger
 
 bl = Fore.CYAN
@@ -19,10 +21,17 @@ def fift_execute_command(file: str, args: List[str], pre_args: Optional[List[str
     if not pre_args:
         pre_args = []
 
-    return [executable['fift'], "-I", f"{config_folder}/fift-libs", *pre_args, "-s", file, *args]
+    answer = [os.path.abspath(executable['fift']), "-I",
+              os.path.abspath(f"{config_folder}/fift-libs"),
+              *pre_args, "-s",
+              os.path.abspath(file),
+              *args]
 
+    return answer
 
-def test_fift(fift_files_locations: List[str], test_file_path: str, cwd: Optional[str] = None):
+
+def test_fift(fift_files_locations: List[str], test_file_path: str, cwd: Optional[str] = None,
+              data_params: Optional[list] = None):
     """
     :param fift_files_locations: files to pass to test.fif
     :param test_file_path: Path to test.fif file
@@ -31,26 +40,68 @@ def test_fift(fift_files_locations: List[str], test_file_path: str, cwd: Optiona
     """
     logger.info(f"🤗 Run tests on {bl}{fift_files_locations}{rs}")
 
+    if not data_params:
+        data_params = [""]
+
     for file in fift_files_locations:
         # Run tests from fift and pass path to file
         # (example of tests can be found in toncli/modules/fift/run_test.fif)
-        subprocess.run(fift_execute_command(test_file_path, [file]), cwd=os.getcwd() if not cwd else cwd)
+        loader = FileSystemLoader(f"{project_root}/modules/fift")
+
+        env = Environment(
+            loader=loader,
+            autoescape=select_autoescape()
+        )
+
+        template = env.get_template(test_file_path)
+
+        run_test_temp_location: str = tempfile.mkstemp(suffix='.fif')[1]
+
+        rendered = template.render(data_path=file)
+
+        with open(run_test_temp_location, 'w', encoding='utf-8') as f:
+            f.write(rendered)
+
+        subprocess.run(fift_execute_command(run_test_temp_location, data_params), cwd=getcwd() if not cwd else cwd)
 
 
 def contract_manipulation(code_path: str, data_path: str, workchain: int, boc_location: str, address_location: str,
-                          cwd: Optional[str] = None) -> Optional[str]:
+                          cwd: Optional[str] = None, data_params: List[str] = None) -> Optional[str]:
     """Run contract_manipulation.fif code"""
+    if not data_params:
+        data_params = [""]
 
     logger.info(f"🥳 Start contract manipulation")
 
-    contract_manipulation_fift_path = f"{project_root}/modules/fift/contract_manipulation.fif"
+    # Load template of transaction_debug
+    loader = FileSystemLoader(f"{project_root}/modules/fift")
+
+    env = Environment(
+        loader=loader,
+        autoescape=select_autoescape()
+    )
+
+    template = env.get_template("data_proxy.fif.template")
+
+    boc_temp_location: str = tempfile.mkstemp(suffix='.boc')[1]
+
+    rendered = template.render(data_path=data_path, file_path=boc_temp_location)
+
+    with open(boc_temp_location, 'w', encoding='utf-8') as f:
+        f.write(rendered)
+
+    command = fift_execute_command(boc_temp_location, data_params)
+    output = subprocess.check_output(command, cwd=getcwd() if not cwd else cwd)
+    output_data = output.decode()
+
+    contract_manipulation_fift_path = os.path.join(project_root, "modules/fift/contract_manipulation.fif")
     command = fift_execute_command(contract_manipulation_fift_path,
-                                   [code_path, data_path, str(workchain), boc_location, address_location])
+                                   [code_path, boc_temp_location, str(workchain), boc_location, address_location])
 
-    output = subprocess.check_output(command, cwd=os.getcwd() if not cwd else cwd)
+    output = subprocess.check_output(command, cwd=getcwd() if not cwd else cwd)
     output_data = output.decode()
 
-    # TODO: fix, get normal address from python...
+    # # TODO: fix, get normal address from python...
     if 'address' in output_data:
         return output_data
     else:
diff --git a/src/toncli/modules/utils/fift/fift.py b/src/toncli/modules/utils/fift/fift.py
index a6c45f2..f93191c 100644
--- a/src/toncli/modules/utils/fift/fift.py
+++ b/src/toncli/modules/utils/fift/fift.py
@@ -1,4 +1,5 @@
 import os
+import platform
 import shlex
 import subprocess
 import sys
@@ -8,7 +9,7 @@
 from colorama import Fore, Style
 
 from toncli.modules.utils.func.func import Func
-from toncli.modules.utils.system.conf import config_folder, executable
+from toncli.modules.utils.system.conf import config_folder, executable, lite_client_tries, getcwd
 from toncli.modules.utils.fift.commands import fift_execute_command
 from toncli.modules.utils.lite_client.commands import lite_client_execute_command
 from toncli.modules.utils.system.log import logger
@@ -32,7 +33,7 @@ def __init__(self, command: str, args: Optional[List[str]] = None, kwargs: Optio
         :param quiet: Is output of lite-client needed
         :param cwd: Project root
         """
-        self.cwd = cwd if cwd else os.getcwd()
+        self.cwd = cwd if cwd else getcwd()
         self.command = command
         self.quiet = quiet
 
@@ -50,7 +51,7 @@ def __init__(self, command: str, args: Optional[List[str]] = None, kwargs: Optio
         self.args = args
 
         # Currently, running command in project root
-        self.project_dir = check_for_needed_files_to_deploy(os.getcwd(), True)
+        self.project_dir = check_for_needed_files_to_deploy(getcwd(), True)
         self.cli_fif_lib = None
 
     def run(self):
@@ -77,33 +78,36 @@ def sendboc(self):
         filename = self.args[0]
 
         # Check that
-        with open(filename, 'r') as f:
+        with open(filename, 'r', encoding='utf-8') as f:
             code = f.read()
 
             if 'saveboc' not in code:
                 logger.error(f"🦷 You need to add {bl}saveboc{rs} to your fif file {gr}{filename}{rs}")
                 sys.exit()
 
-        # remove folder
-        if '/' in filename:
-            filename = filename.split('/')[-1]
+        if platform.system() == 'Windows':
+            if '\\' in filename:
+                filename = os.path.split(filename)[-1]
+        else:
+            if '/' in filename:
+                filename = filename.split('/')[-1]
 
         # get file-base
         if '.' in filename:
             filename = filename.split('.')[0]
 
-        if os.path.exists(f'{self.cwd}/build/boc'):
-            path = f'{self.cwd}/build/boc/{filename}.boc'
+        if os.path.exists(os.path.abspath(f'{self.cwd}/build/boc')):
+            path = os.path.abspath(f'{self.cwd}/build/boc/{filename}.boc')
         else:
             # if not project root - create temp directory
             path = tempfile.mkdtemp()
-            path = f"{path}/{filename}.boc"
+            path = os.path.abspath(f"{path}/{filename}.boc")
 
         logger.info(f"💾 Will save BOC to {gr}{path}{rs}")
 
         # If we never created cli.fif in project root
         if self.project_dir:
-            self.cli_fif_lib = build_cli_lib(f'{self.cwd}/build/cli.fif', {  # Generate cli.fif
+            self.cli_fif_lib = build_cli_lib(os.path.abspath(f'{self.cwd}/build/cli.fif'), {  # Generate cli.fif
                 "is_project": '1',
                 "project_root": self.cwd,
                 "build_path": path,
@@ -113,23 +117,34 @@ def sendboc(self):
         elif not self.project_dir:
             self.cli_fif_lib = build_cli_lib(render_kwargs={
                 "is_project": '0',
-                "project_root": f'/tmp',
+                "project_root": tempfile.gettempdir(),
                 "build_path": path
             })
 
         # generate BOC file
         # Our own cli.fif file need to be added before run
-        command = fift_execute_command(file=self.args[0], args=[*self.args[1:]], pre_args=["-L", self.cli_fif_lib])
+        command = fift_execute_command(file=self.args[0], args=[*self.args[1:], *self.kwargs['fift_args']], pre_args=["-L", self.cli_fif_lib])
 
-        subprocess.run(command, cwd=self.cwd)
+        subprocess.run(command, cwd=os.path.abspath(self.cwd))
 
         # send boc file
         command = lite_client_execute_command(self.kwargs['net'], ['-v', '2', '-c', f'sendfile {path}'],
                                               update_config=self.kwargs['update'])
         output = None
         if self.quiet:
-            output = open(os.devnull, 'w')
-        subprocess.run(command, stdout=output, stderr=output, cwd=self.cwd)
+            output = open(os.devnull, 'w', encoding='utf-8')
+
+        for _try in range(lite_client_tries):
+            try:
+                output = subprocess.check_output(command, cwd=os.path.abspath(self.cwd))
+                if 'Connection refused' in output.decode():
+                    continue
+                break
+            except Exception as e:
+                if _try != 1:
+                    continue
+                else:
+                    logger.error(f"😢 Error in lite-client execution: {' '.join(command)}")
 
     def run_script(self):
         """Runs fift in script mode on file"""
@@ -138,7 +153,7 @@ def run_script(self):
             sys.exit()
 
         if not len(self.kwargs['fift_args']):
-            self.kwargs['fift_args'] = ["-I", f"{config_folder}/fift-libs", "-s"]
+            self.kwargs['fift_args'] = ["-I", os.path.abspath(f"{config_folder}/fift-libs"), "-s"]
         else:
             self.kwargs['fift_args'].append("-s")
 
@@ -155,12 +170,12 @@ def run_interactive(self):
         logger.info(f"🖥  Run interactive fift for you ({bl}Ctrl+c{rs} to exit)")
         logger.info(f"🖥  A simple Fift interpreter. Type `bye` to quit, or `words` to get a list of all commands")
         if not len(self.kwargs['fift_args']):
-            self.kwargs['fift_args'] = ["-I", f"{config_folder}/fift-libs", "-i"]
+            self.kwargs['fift_args'] = ["-I", os.path.abspath(f"{config_folder}/fift-libs"), "-i"]
         else:
             self.kwargs['fift_args'].append("-i")
 
         command = [executable['fift'], *self.kwargs['fift_args']]
-        logger.debug(f"🖥  Command ({command})")
+        logger.debug(f"🖥  Command ({' '.join(command)})")
 
         try:
             subprocess.run(command)
diff --git a/src/toncli/modules/utils/func/commands.py b/src/toncli/modules/utils/func/commands.py
index dae397a..ad1f4d1 100644
--- a/src/toncli/modules/utils/func/commands.py
+++ b/src/toncli/modules/utils/func/commands.py
@@ -6,7 +6,7 @@
 import yaml
 from colorama import Fore, Style
 
-from toncli.modules.utils.system.conf import config_folder, executable
+from toncli.modules.utils.system.conf import config_folder, executable, getcwd
 from toncli.modules.utils.system.log import logger
 from toncli.modules.utils.system.project import migrate_project_struction
 from toncli.modules.utils.system.project_conf import ProjectConf, TonProjectConfig
@@ -19,7 +19,8 @@
 def build(project_root: str,
           cwd: Optional[str] = None,
           func_args: List[str] = None,
-          contracts: List[TonProjectConfig] = None) -> Optional[str]:
+          contracts: List[TonProjectConfig] = None,
+          use_tests_lib: bool = False) -> Optional[str]:
     """
     Build func file(s) and save result fift file to location
 
@@ -27,11 +28,11 @@ def build(project_root: str,
     :param func_args: add arguments to func
     :param project_root: Files to build in needed order
     :param cwd: If you need to change root of running script pass it here
+    :param use_tests_lib: Use stdlib-tests.func
     :return:
     """
-    project_config = ProjectConf(project_root)
-
     if not contracts:
+        project_config = ProjectConf(project_root)
         contracts = project_config.contracts
 
     if not func_args:
@@ -39,16 +40,29 @@ def build(project_root: str,
 
     output = []
     for contract in contracts:
-        output.append(build_files(contract.func_files_locations, contract.to_save_location, func_args, cwd))
+        output.append(
+            build_files(contract.func_files_locations, contract.to_save_location, func_args, cwd,
+                        use_tests_lib=use_tests_lib))
+
+        if len(contract.func_tests_files_locations) and use_tests_lib:
+            output.append(
+                build_files([f"{config_folder}/func-libs/tests-helpers.func", *contract.func_tests_files_locations],
+                            contract.to_save_tests_location, [], cwd,
+                            use_tests_lib=True))
 
     return "\n".join(list(map(str, output)))
 
 
 def build_files(func_files_locations: List[str], to_save_location: str, func_args: List[str] = None,
-                cwd: Optional[str] = None):
-    build_command = [executable['func'], *func_args, "-o", to_save_location, "-SPA",
-                     f"{config_folder}/func-libs/stdlib.fc", *func_files_locations]
-    get_output = subprocess.check_output(build_command, cwd=os.getcwd() if not cwd else cwd)
+                cwd: Optional[str] = None, use_tests_lib: bool = False):
+    build_command = [os.path.abspath(executable['func']), *func_args, "-o",
+                     os.path.abspath(to_save_location), "-SPA",
+                     os.path.abspath(
+                         f"{config_folder}/func-libs/stdlib.func") if not use_tests_lib else os.path.abspath(
+                         f"{config_folder}/func-libs/stdlib-tests.func"),
+                     *[os.path.abspath(i) for i in func_files_locations]]
+
+    get_output = subprocess.check_output(build_command, cwd=getcwd() if not cwd else os.path.abspath(cwd))
 
     if get_output:
         return get_output.decode()
diff --git a/src/toncli/modules/utils/func/func.py b/src/toncli/modules/utils/func/func.py
index 8aaac7f..307afb9 100644
--- a/src/toncli/modules/utils/func/func.py
+++ b/src/toncli/modules/utils/func/func.py
@@ -1,4 +1,5 @@
 import os
+import platform
 import shlex
 import subprocess
 import sys
@@ -9,7 +10,7 @@
 from toncli.modules.utils.system.log import logger
 from toncli.modules.utils.system.project import check_for_needed_files_to_deploy
 from toncli.modules.utils.func.commands import build as fift_build, build_files
-from toncli.modules.utils.system.conf import executable
+from toncli.modules.utils.system.conf import executable, getcwd
 from toncli.modules.utils.fift.commands import fift_execute_command
 
 bl = Fore.CYAN
@@ -32,7 +33,7 @@ def __init__(self, command: Optional[str] = None, args: Optional[List[str]] = No
         self.args = args if args else []
 
         # Currently, running command in project root
-        self.project_dir = check_for_needed_files_to_deploy(os.getcwd(), False)
+        self.project_dir = check_for_needed_files_to_deploy(getcwd(), False)
 
     def run(self):
         if not self.command or self.command == 'build':
@@ -53,33 +54,31 @@ def build(self):
         # If file to build is passed
         if len(self.args):
             file_path = self.args[-1]
-
-            if '/' in file_path:
-                file_path = file_path.split('/')[-1]
+            file_path = file_path.split(os.path.sep)[-1]
 
             # Parse file base
             to_save_location = f"{file_path.split('.')[0]}.fif"
 
             if self.project_dir:
-                to_save_location = f"{os.getcwd()}/build/{to_save_location}"
+                to_save_location = os.path.abspath(f"{getcwd()}/build/{to_save_location}")
 
-            self.args = list(map(lambda file: f"{os.getcwd()}/{file}", self.args))
+            self.args = list(map(lambda file: os.path.abspath(f"{getcwd()}/{file}"), self.args))
 
-            build_files(self.args, to_save_location, self.kwargs['func_args'], cwd=os.getcwd())
+            build_files(self.args, to_save_location, self.kwargs['func_args'], cwd=getcwd())
 
         else:
             if not self.project_dir:
                 logger.error(
-                    f"🤟 It is not project root [{bl}{os.getcwd()}{rs}] - I can't build project without project")
+                    f"🤟 It is not project root [{bl}{getcwd()}{rs}] - I can't build project without project")
                 sys.exit()
 
-            to_save_location = f"{os.getcwd()}/build"
+            to_save_location = os.path.abspath(f"{getcwd()}/build")
 
             # Build code
-            fift_build(os.getcwd(), cwd=os.getcwd())
+            fift_build(getcwd(), cwd=getcwd())
 
-        build = [i.replace(os.getcwd(), '') for i in self.args]
-        location = to_save_location.replace(os.getcwd(), '')
+        build = [i.replace(getcwd(), '') for i in self.args]
+        location = to_save_location.replace(getcwd(), '')
         logger.info(f"🥌 Build {bl}{build}{rs} {gr}successfully{rs}, check out {gr}.{location}{rs}")
 
         if run_code:
diff --git a/src/toncli/modules/utils/lite_client/commands.py b/src/toncli/modules/utils/lite_client/commands.py
index 714550e..9453749 100644
--- a/src/toncli/modules/utils/lite_client/commands.py
+++ b/src/toncli/modules/utils/lite_client/commands.py
@@ -6,8 +6,9 @@
 from colorama import Fore, Style
 from requests import get as http_get
 
-from toncli.modules.utils.system.conf import executable, config_folder, config_uri
+from toncli.modules.utils.system.conf import executable, config_folder, config_uri, getcwd
 from toncli.modules.utils.system.log import logger
+from toncli.modules.utils.system.conf import lite_client_tries
 
 gr = Fore.GREEN
 bl = Fore.CYAN
@@ -33,11 +34,11 @@ def get_network_config_path(network: str, update_config: bool = False) -> str:
         # need to download config file and save it
         r = http_get(config_uri[network], stream=True)
         if r.status_code == 200:
-            with open(f"{config_folder}/{filename}", 'wb') as f:
+            with open(os.path.abspath(f"{config_folder}/{filename}"), 'wb') as f:
                 for chunk in r:
                     f.write(chunk)
 
-    return f"{config_folder}/{filename}"
+    return os.path.abspath(f"{config_folder}/{filename}")
 
 
 def lite_client_execute_command(network: str, args: List[str], update_config=False, ) -> List[str]:
@@ -50,7 +51,7 @@ def lite_client_execute_command(network: str, args: List[str], update_config=Fal
     :return:
     """
     network = get_network_config_path(network, update_config)
-    return [executable['lite-client'], "-C", network, *args]
+    return [os.path.abspath(executable['lite-client']), "-v", "3", "--timeout", "3", "-C", network, *args]
 
 
 def get_account_status(network: str, address: str, cwd: Optional[str] = None,
@@ -68,8 +69,22 @@ def get_account_status(network: str, address: str, cwd: Optional[str] = None,
     command = lite_client_execute_command(network, ['-v', '0', '-c',
                                                     f'getaccount {address} {block_id_ext if block_id_ext else ""}'],
                                           update_config=update_config)
-    account_info = subprocess.check_output(command, cwd=os.getcwd() if not cwd else cwd)
-    account_info = account_info.decode()
+
+    _try = 0
+    e = None
+    while _try < lite_client_tries + 1:
+        try:
+            account_info = subprocess.check_output(command, cwd=getcwd() if not cwd else os.path.abspath(cwd))
+            account_info = account_info.decode()
+            break
+        except Exception as exc:
+            _try += 1
+            e = exc
+
+    if _try == lite_client_tries + 1:
+        logger.error(f"😢 Error running {' '.join(command)}")
+        raise e
+
     is_inited = 'account_uninit' not in account_info
 
     account_info = account_info.split('\n')
@@ -94,6 +109,35 @@ def send_boc(network: str, path: str, cwd: Optional[str] = None, update_config:
     """
     command = lite_client_execute_command(network, ['-v', '2', '-c', f'sendfile {path}'], update_config=update_config)
     if not get_output:
-        subprocess.run(command, cwd=os.getcwd() if not cwd else cwd)
+        _try = 0
+        e = None
+        while _try < lite_client_tries + 1:
+            try:
+                subprocess.run(command, cwd=getcwd() if not cwd else os.path.abspath(cwd))
+                break
+            except Exception as exc:
+                e = exc
+                _try += 1
+
+        if _try == lite_client_tries + 1:
+            logger.error(f"😢 Error running {' '.join(command)}")
+            raise e
     else:
-        return subprocess.check_output(command, cwd=os.getcwd() if not cwd else cwd).decode()
+        _try = 0
+        e = None
+        while _try < lite_client_tries + 1:
+            try:
+                output = subprocess.check_output(command, cwd=getcwd() if not cwd else os.path.abspath(cwd)).decode()
+                break
+            except Exception as exc:
+                e = exc
+                _try += 1
+
+        if _try == lite_client_tries + 1:
+            logger.error(f"😢 Error running {' '.join(command)}")
+            raise exc
+        return output
+
+
+if __name__ == "__main__":
+    print(get_account_status('testnet', 'kQDmJ8fyL7VWitcVXv1-CL4iu-xo5mXlSMZCXuIPxyy9yAHG'))
diff --git a/src/toncli/modules/utils/lite_client/lite_client.py b/src/toncli/modules/utils/lite_client/lite_client.py
index 9098f6a..eab937f 100644
--- a/src/toncli/modules/utils/lite_client/lite_client.py
+++ b/src/toncli/modules/utils/lite_client/lite_client.py
@@ -4,7 +4,7 @@
 from typing import Optional, List
 from toncli.modules.utils.system.log import logger
 from toncli.modules.utils.lite_client.commands import lite_client_execute_command
-
+from toncli.modules.utils.system.conf import lite_client_tries
 
 class LiteClient:
     def __init__(self, command: str, args: Optional[List[str]] = None, kwargs: Optional[dict] = None,
@@ -41,7 +41,7 @@ def run_interactive(self):
         subprocess.run(command)
 
     def run_command(self) -> Optional[bytes]:
-        for _try in range(2):
+        for _try in range(lite_client_tries):
             try:
                 command = lite_client_execute_command(self.kwargs['net'],
                                                       [*self.kwargs['lite_client_args'], '-c',
@@ -57,7 +57,7 @@ def run_command(self) -> Optional[bytes]:
                 if _try != 1:
                     continue
                 else:
-                    console.error(f"😢 Error in lite-client execution")
+                    logger.error(f"😢 Error in lite-client execution: {' '.join(command)}")
 
     def run_safe(self):
         output = self.run()
diff --git a/src/toncli/modules/utils/lite_client/parser.py b/src/toncli/modules/utils/lite_client/parser.py
new file mode 100644
index 0000000..adb76bf
--- /dev/null
+++ b/src/toncli/modules/utils/lite_client/parser.py
@@ -0,0 +1,28 @@
+def split_get_output(output: str):
+    """'
+    Parse output like:
+    -1 0 CS{Cell{...} bits: 64..66; refs: 0..0} CS{Cell{...} bits: 66..333; refs: 0..0} C{...}
+    To:
+    [-1, 0, "CS{Cell{...} bits: 64..66; refs: 0..0}", "CS{Cell{...} bits: 66..333; refs: 0..0}", "C{...}"]
+
+    """
+
+    data = output.split()
+    result = []
+
+    to_fix = 0
+    for i in data:
+        if to_fix > 0:
+            result[-1] += f" {i}"
+        else:
+            result.append(i)
+
+        tmp_to_fix = i.count('{')
+        tmp_to_not_fix = i.count("}")
+        to_fix += tmp_to_fix - tmp_to_not_fix
+
+    return result
+
+
+if __name__ == "__main__":
+    print(split_get_output("-1 0 CS{Cell{...} bits: 64..66; refs: 0..0} CS{Cell{...} bits: 66..333; refs: 0..0} C{...}"))
diff --git a/src/toncli/modules/utils/system/check_executable.py b/src/toncli/modules/utils/system/check_executable.py
index 339a5dd..77c0308 100644
--- a/src/toncli/modules/utils/system/check_executable.py
+++ b/src/toncli/modules/utils/system/check_executable.py
@@ -1,13 +1,15 @@
 import os
+import platform
 import shutil
 import subprocess
 from typing import Optional, List, Dict, Tuple
+
 from toncli.modules.utils.system.log import logger
 
 
 def safe_get_version(executable: str) -> Optional[List[str]]:
     try:
-        output = subprocess.check_output([executable, '-V'])
+        output = subprocess.check_output([os.path.abspath(executable), '-V'])
         output = output.decode()
 
         if ' build information:' in output:
@@ -20,11 +22,44 @@ def safe_get_version(executable: str) -> Optional[List[str]]:
 
 
 def check_executable(executable_config: Dict) -> Tuple[Dict, bool]:
+    from toncli.modules.utils.system.conf import getcwd
+
     config = {}
     is_executable_changes = False
 
     for item in ['func', 'fift', 'lite-client']:
-        if not os.path.exists(executable_config[item]):
+        if not executable_config[item] or len(executable_config[item]) == 0:
+            founded_executable = False
+
+            if platform.system() == 'Windows':
+                item_name = f'{item}.exe'
+            else:
+                item_name = item
+
+            if item_name in os.listdir(getcwd()):
+                item_path = os.path.abspath(os.path.join(getcwd(), item_name))
+                version_output = safe_get_version(item_path)
+
+                if version_output is not None and len(version_output) == 2:
+                    is_executable_changes = True
+                    founded_executable = True
+                    config[item] = item_path
+
+                    logger.info(f"Adding path to executable {item} success!")
+
+            while not founded_executable:
+                logger.warning(f"🤖 Can't find executable for {item}, please specify it, e.g.: /usr/bin/{item}")
+                config[item] = input("Path: ")
+
+                version_output = safe_get_version(config[item])
+
+                if version_output is not None and len(version_output) == 2:
+                    is_executable_changes = True
+                    founded_executable = True
+                else:
+                    logger.warning("😅 Path is not correct, please double check it")
+
+        elif not os.path.exists(os.path.abspath(executable_config[item])):
             executable_path = shutil.which(item)
 
             if executable_path:
diff --git a/src/toncli/modules/utils/system/conf.py b/src/toncli/modules/utils/system/conf.py
index 985afc6..472088d 100644
--- a/src/toncli/modules/utils/system/conf.py
+++ b/src/toncli/modules/utils/system/conf.py
@@ -1,10 +1,12 @@
 import configparser
 import os
+import platform
 import shutil
+import tempfile
 
 from appdirs import user_config_dir
 from colorama import Fore, Style
-
+from copy import deepcopy
 from toncli.modules.utils.system.check_executable import safe_get_version, check_executable
 from toncli.modules.utils.system.log import logger
 
@@ -13,15 +15,37 @@
 rs = Style.RESET_ALL
 
 project_root = os.path.realpath(__file__)
-project_root = "/".join(project_root.split("/")[:-4])  # get root folder of toncli/src
+
+project_root = os.path.abspath(os.path.sep.join(project_root.split(os.path.sep)[:-4]))  # get root folder of toncli/src
 
 # Folder to store config files in
 config_folder = user_config_dir('toncli')
 
+name_replace = ['', '']
+
+# fix win encoding
+# todo: find normal fix
+if platform.system() == 'Windows':
+    old_user = project_root.split(os.path.sep)[2]  # Old cyrillic name
+    user = config_folder.split(os.path.sep)[2]  # New name (in tempfile it's encoded)
+    project_root = project_root.replace(old_user, user)  # New path with encoded cyrillic name of user
+    name_replace = [old_user, user]
+
+
+def getcwd():
+    path = os.getcwd()
+
+    # fix win cyrillic
+    if platform.system() == 'Windows':
+        path = path.replace(name_replace[0], name_replace[1])
+
+    return path
+
+
 # Create if not exist
-if not os.path.exists(config_folder):
+if not os.path.exists(os.path.abspath(f"{config_folder}/config.ini")):
     config = configparser.ConfigParser()
-    config.read(f'{project_root}/config.ini')
+    config.read(os.path.abspath(f'{project_root}/config.ini'))
 
     config['executable'] = {
         'func': '',
@@ -40,16 +64,16 @@
 
     os.makedirs(config_folder)
 
-    with open(f'{config_folder}/config.ini', 'w') as config_file:
+    with open(os.path.abspath(f'{config_folder}/config.ini'), 'w') as config_file:
         config.write(config_file)
 
-    shutil.copytree(f"{project_root}/lib/", f"{config_folder}",
+    shutil.copytree(os.path.abspath(f"{project_root}/lib/"), os.path.abspath(f"{config_folder}"),
                     dirs_exist_ok=True)  # copy all fift / func libs
 
-config_file = f"{config_folder}/config.ini"
+config_file = os.path.abspath(f"{config_folder}/config.ini")
 
 config = configparser.ConfigParser()
-config.read(config_file)
+config.read(os.path.abspath(f"{config_folder}/config.ini"))
 
 if 'toncenter_mainnet' not in config['DEFAULT'] or 'toncenter_testnet' not in config['DEFAULT']:
     config['DEFAULT']['toncenter_mainnet'] = 'https://toncenter.com/api/v2'
@@ -63,12 +87,14 @@
 # URI to get config from
 config_uri = {
     'testnet': main_config.get('testnet'),
-    'mainnet': main_config.get('mainnet')
+    'mainnet': main_config.get('mainnet'),
+    'ownnet': main_config.get('ownnet', ''),
 }
 
 toncenter = {
     'mainnet': main_config.get('toncenter_mainnet'),
     'testnet': main_config.get('toncenter_testnet'),
+    'ownnet': main_config.get('toncenter_ownnet', ''),
 }
 
 # Here we need to correctly define executable path
@@ -77,11 +103,13 @@
 if is_executable_changes:
     config['executable'] = new_executable
 
-    with open(f'{config_folder}/config.ini', 'w') as config_file:
-        config.write(config_file)
+    with open(os.path.abspath(f'{config_folder}/config.ini'), 'w') as cfg_path:
+        config.write(cfg_path)
 
 executable = {
     'fift': new_executable['fift'],
     'func': new_executable['func'],
     'lite-client': new_executable['lite-client'],
 }
+
+lite_client_tries = 7
diff --git a/src/toncli/modules/utils/system/project.py b/src/toncli/modules/utils/system/project.py
index 2c3abea..be0bd1d 100644
--- a/src/toncli/modules/utils/system/project.py
+++ b/src/toncli/modules/utils/system/project.py
@@ -57,7 +57,7 @@ def migrate_project_struction(old_version: str, cwd: str):
         logger.warning("🙀 Detected old version of project, migrate to newer one")
 
         func_files_path = f"{cwd}/func/files.yaml"
-        with open(f"{func_files_path}", "r") as stream:
+        with open(f"{func_files_path}", "r", encoding='utf-8') as stream:
             try:
                 func_configuration = yaml.safe_load(stream)
             except yaml.YAMLError as exc:
@@ -74,11 +74,12 @@ def migrate_project_struction(old_version: str, cwd: str):
 
         yaml_structure = yaml.dump(new_structure)
 
-        with open(f"{cwd}/project.yaml", "w") as stream:
+        with open(os.path.abspath(f"{cwd}/project.yaml"), "w", encoding='utf-8') as stream:
             stream.write(yaml_structure)
 
-        if os.path.exists(f'{cwd}/build/address_text'):
-            shutil.move(f"{cwd}/build/address_text", f"{cwd}/build/contract_address")
+        if os.path.exists(os.path.abspath(f'{cwd}/build/address_text')):
+            shutil.move(os.path.abspath(f"{cwd}/build/address_text"),
+                        os.path.abspath(f"{cwd}/build/contract_address"))
 
         os.remove(func_files_path)
         logger.info("☀ Successful migrated to v0.0.15 project structure")
diff --git a/src/toncli/modules/utils/system/project_conf.py b/src/toncli/modules/utils/system/project_conf.py
index e591a5d..ff528a6 100644
--- a/src/toncli/modules/utils/system/project_conf.py
+++ b/src/toncli/modules/utils/system/project_conf.py
@@ -1,3 +1,5 @@
+import os.path
+import platform
 import sys
 from typing import List
 
@@ -13,13 +15,30 @@
 
 class TonProjectConfig:
     def __init__(self, func_files_locations: List[str], name: str, to_save_location: str, data: str, boc: str,
-                 address: str):
-        self.data = data
+                 address: str, func_tests_files_locations: List[str], to_save_tests_location: str):
+        self.name = name
         self.boc = boc
         self.address = address
+        self.data = data
         self.to_save_location = to_save_location
-        self.name = name
         self.func_files_locations = func_files_locations
+        self.func_tests_files_locations = func_tests_files_locations
+        self.to_save_tests_location = to_save_tests_location
+
+        if platform.system() == 'Windows':
+            from toncli.modules.utils.system.conf import name_replace
+
+            self.boc = boc.replace(name_replace[0], name_replace[1])
+            self.address = address.replace(name_replace[0], name_replace[1])
+            self.data = data.replace(name_replace[0], name_replace[1])
+            self.to_save_location = to_save_location.replace(name_replace[0], name_replace[1])
+            self.to_save_tests_location = to_save_tests_location.replace(name_replace[0], name_replace[1])
+            self.func_files_locations = [i.replace(name_replace[0], name_replace[1]) for i in func_files_locations]
+            self.func_tests_files_locations = [i.replace(name_replace[0], name_replace[1]) for i in
+                                               func_tests_files_locations]
+
+    def __repr__(self):
+        return f"<TonProjectConfig {self.name}>"
 
 
 class ProjectConf:
@@ -27,7 +46,7 @@ def __init__(self, project_root: str):
         """Parse project.yaml to correctly build project"""
         self.contracts: List[TonProjectConfig] = []
 
-        with open(f"{project_root}/project.yaml", "r") as stream:
+        with open(os.path.abspath(f"{project_root}/project.yaml"), "r", encoding='utf-8') as stream:
             try:
                 func_configuration = yaml.safe_load(stream)
             except yaml.YAMLError as exc:
@@ -39,11 +58,18 @@ def __init__(self, project_root: str):
             contract_config = func_configuration[contract]
             func_files_locations = [f"{project_root}/{file_path}" for file_path in contract_config['func']]
 
+            if 'tests' in contract_config:
+                func_tests_files_locations = [f"{project_root}/{file_path}" for file_path in contract_config['tests']]
+            else:
+                func_tests_files_locations = []
+
             self.contracts.append(TonProjectConfig(**{
                 'func_files_locations': func_files_locations,
+                'func_tests_files_locations': func_tests_files_locations,
                 'name': contract,
                 'boc': f"{project_root}/build/boc/{contract}.boc",
                 'address': f"{project_root}/build/{contract}_address",
                 'to_save_location': f"{project_root}/build/{contract}.fif",
+                'to_save_tests_location': f"{project_root}/build/{contract}_tests.fif",
                 'data': f"{project_root}/{contract_config['data']}" if 'data' in contract_config else ""
             }))
diff --git a/src/toncli/modules/utils/ton/cell.py b/src/toncli/modules/utils/ton/cell.py
new file mode 100644
index 0000000..079f2d9
--- /dev/null
+++ b/src/toncli/modules/utils/ton/cell.py
@@ -0,0 +1,57 @@
+from bitstring import BitString
+import math
+from typing import Optional
+
+
+def deserialize(data: str, cut_start: Optional[int] = None, cut_end: Optional[int] = None) -> str:
+    """
+    Deserialize cell (warning: it's not full deserialization, it's only for get methods thrue lite client)
+
+    :param data: HEX data
+    :param cut_start: Data bits cut start
+    :param cut_end: Data bits cut end
+    :return: Return BIN
+    """
+    _bytes = BitString(hex=data)
+
+    # 3.1.4. Standard cell representation
+
+    # Two descriptor bytes d1 and d2 are serialized first. Byte d1 equals
+    # r+8s+32l, where 0 ≤ r ≤ 4 is the quantity of cell references contained
+    # in the cell, 0 ≤ l ≤ 3 is the level of the cell, and 0 ≤ s ≤ 1 is 1 for
+    # exotic cells and 0 for ordinary cells.
+
+    d1 = int(_bytes.bytes[0])
+
+    l = d1 // 32  # level of cell
+    s = (d1 % 32) // 8  # is cell exotic
+    r = ((d1 % 32) % 8)  # refs
+
+    # _bytes[1] Byte d2 equals bb/8c+db/8e, where
+    # 0 ≤ b ≤ 1023 is the quantity of data bits in c.
+
+    b = math.ceil((_bytes.bytes[1]) / 2)  # data bits
+    data = _bytes.bin[2 * 8:]  # cut d1 & d2
+    data = data[:b * 8]  # up to data end
+
+    if int(_bytes.bytes[1]) % 2 != 0:
+        to_cut = 0
+
+        for i in reversed(data):
+            if int(i) == 1:
+                to_cut += 1
+                break
+            else:
+                to_cut += 1
+
+        data = data[:-1 * to_cut]
+
+    cell_bits_length = len(data)
+    if not cut_start:
+        return data
+    else:
+        return data[cut_start:cut_end]
+
+
+if __name__ == "__main__":
+    print(deserialize("015300000000000000002003bf5f88fb118ac18af94fee62930bf5ab60682b3c03d72c9a6f45f841ac7dcc04"))
diff --git a/src/toncli/modules/utils/transaction.py b/src/toncli/modules/utils/transaction.py
index faf2f84..f9018e7 100644
--- a/src/toncli/modules/utils/transaction.py
+++ b/src/toncli/modules/utils/transaction.py
@@ -8,6 +8,7 @@
 from toncli.modules.utils.system.conf import toncenter, project_root
 from toncli.modules.utils.fift.fift import Fift
 from toncli.modules.utils.lite_client.commands import get_account_status
+from toncli.modules.utils.system.log import logger
 import base64
 import urllib.parse
 
@@ -54,13 +55,24 @@ def run_transaction(network: str, smc_address: str, logical_time: str, tx_hash:
             prev_block = i.split()[-1]
             break
 
-    # Get account balance
-    amount, _ = get_account_status(network, smc_address, update_config=False, block_id_ext=prev_block)
-    amount *= 1000000000
+    try:
+        # Get account balance
+        amount, _ = get_account_status(network, smc_address, update_config=False)  # , block_id_ext=prev_block)
+        amount *= 1000000000
+    except:
+        amount = 0
 
     # TODO: use lite client
-    answer = r.get(
-        f"{toncenter[network]}/getTransactions?address={smc_address}&limit=1&lt={logical_time}&hash={tx_hash}&archival=true")
+    url = f"{toncenter[network]}/getTransactions?address={smc_address}&limit=1&lt={logical_time}&hash={tx_hash}&archival=true"
+    logger.info(f"Get: {url}")
+    headers = {
+        'Content-Type': 'application/json',
+        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
+        'X-API-Key': '8288886278c90c1656f622ee779656951809c39da7703281993e704049b11ca9'
+    }
+
+    answer = r.get(url, timeout=1)
+    logger.info(f"Got answer!")
     result = answer.json()["result"][0]
 
     # Get message value
@@ -81,7 +93,7 @@ def run_transaction(network: str, smc_address: str, logical_time: str, tx_hash:
 
     # Save account code
     lite_client = LiteClient('saveaccountcode',
-                             args=[to_save_location_c3, smc_address, prev_block],
+                             args=[to_save_location_c3, smc_address],  # prev_block],
                              kwargs={'lite_client_args': '-v 0',
                                      'net': network,
                                      'update': False},
@@ -90,7 +102,7 @@ def run_transaction(network: str, smc_address: str, logical_time: str, tx_hash:
 
     # Save account data
     lite_client = LiteClient('saveaccountdata',
-                             args=[to_save_location_c4, smc_address, prev_block],
+                             args=[to_save_location_c4, smc_address],  # prev_block],
                              kwargs={'lite_client_args': '-v 0',
                                      'net': network,
                                      'update': False},
@@ -106,6 +118,7 @@ def run_transaction(network: str, smc_address: str, logical_time: str, tx_hash:
                                      'update': False},
                              get_output=True)
     lite_client.run()
+    print(smc_address)
 
     # Add info to Jinja template
     render_kwargs = {
@@ -118,7 +131,7 @@ def run_transaction(network: str, smc_address: str, logical_time: str, tx_hash:
         'time': time,
         'smc_address': smc_address,
         'trans_lt': str(logical_time),
-        'amount': amount,
+        'amount': int(amount),
         'function': str(function)
     }
 
@@ -135,14 +148,14 @@ def run_transaction(network: str, smc_address: str, logical_time: str, tx_hash:
     rendered = template.render(**render_kwargs)
 
     if save_location:
-        with open(save_location, 'w') as f:
+        with open(save_location, 'w', encoding='utf-8') as f:
             f.write(rendered)
     else:
-        with open(to_save_location, 'w') as f:
+        with open(to_save_location, 'w', encoding='utf-8') as f:
             f.write(rendered)
-
-            # Run generated by jinja fift script
-        fift = Fift('run', args=[to_save_location, prev_block])
+        print(to_save_location)
+        # Run generated by jinja fift script
+        fift = Fift('run', args=[to_save_location])  # prev_block])
         fift.run()
 
 
diff --git a/src/toncli/projects/external_code/.gitignore b/src/toncli/projects/external_code/.gitignore
new file mode 100644
index 0000000..378b0b4
--- /dev/null
+++ b/src/toncli/projects/external_code/.gitignore
@@ -0,0 +1,1 @@
+*.pk
diff --git a/src/toncli/projects/external_code/fift/load_c3_and_c4.fif b/src/toncli/projects/external_code/fift/load_c3_and_c4.fif
index 06bdfe0..f91ecd3 100644
--- a/src/toncli/projects/external_code/fift/load_c3_and_c4.fif
+++ b/src/toncli/projects/external_code/fift/load_c3_and_c4.fif
@@ -7,7 +7,7 @@
 
 "build/boc/c3.boc" file>B // load file to bytes
  B>boc // deserializes bag of cells
- constant code // save as code
+ constant code // save as cod
 
 // You can do in bash: toncli lc saveconfig ./build/boc/config.boc
 // Ad comment null, and uncomment next line
diff --git a/src/toncli/projects/external_code/func/code.fc b/src/toncli/projects/external_code/func/code.func
similarity index 100%
rename from src/toncli/projects/external_code/func/code.fc
rename to src/toncli/projects/external_code/func/code.func
diff --git a/src/toncli/projects/external_data/.gitignore b/src/toncli/projects/external_data/.gitignore
new file mode 100644
index 0000000..378b0b4
--- /dev/null
+++ b/src/toncli/projects/external_data/.gitignore
@@ -0,0 +1,1 @@
+*.pk
diff --git a/src/toncli/projects/external_data/build/code.fif b/src/toncli/projects/external_data/build/code.fif
index 78732cf..9e27434 100644
--- a/src/toncli/projects/external_data/build/code.fif
+++ b/src/toncli/projects/external_data/build/code.fif
@@ -1,5 +1,5 @@
 "Asm.fif" include
-// automatically generated from `/home/tvorogme/.config/toncli/func-libs/stdlib.fc` `/home/tvorogme/projects/toncli/src/projects/external_data/func//code.fc`
+// automatically generated from `/home/tvorogme/.config/toncli/func-libs/stdlib.func` `/home/tvorogme/projects/toncli/src/projects/external_data/func//code.func`
 PROGRAM{
   DECLPROC main
   main PROC:<{
diff --git a/src/toncli/projects/external_data/func/code.fc b/src/toncli/projects/external_data/func/code.func
similarity index 100%
rename from src/toncli/projects/external_data/func/code.fc
rename to src/toncli/projects/external_data/func/code.func
diff --git a/src/toncli/projects/external_data/project.yaml b/src/toncli/projects/external_data/project.yaml
index 9531496..705b974 100644
--- a/src/toncli/projects/external_data/project.yaml
+++ b/src/toncli/projects/external_data/project.yaml
@@ -1,3 +1,3 @@
 contract:
   func:
-    - func/code.fc
+    - func/code.func
diff --git a/src/toncli/projects/wallet/.gitignore b/src/toncli/projects/wallet/.gitignore
new file mode 100644
index 0000000..378b0b4
--- /dev/null
+++ b/src/toncli/projects/wallet/.gitignore
@@ -0,0 +1,1 @@
+*.pk
diff --git a/src/toncli/projects/wallet/README.md b/src/toncli/projects/wallet/README.md
index 8203816..95393f7 100644
--- a/src/toncli/projects/wallet/README.md
+++ b/src/toncli/projects/wallet/README.md
@@ -5,5 +5,5 @@ Deployed by [toncli](https://github.com/disintar/toncli)
 ### Usage
 
 - `toncli run fift/data.fif`
-- `toncli run func/code.fc`
-- `toncli deploy -n tesnet -wc 0`
\ No newline at end of file
+- `toncli run func/code.func`
+- `toncli deploy -n testnet -wc 0`
\ No newline at end of file
diff --git a/src/toncli/projects/wallet/fift/examples/parse_get_cell.fif b/src/toncli/projects/wallet/fift/examples/parse_get_cell.fif
index 97a0854..3775312 100644
--- a/src/toncli/projects/wallet/fift/examples/parse_get_cell.fif
+++ b/src/toncli/projects/wallet/fift/examples/parse_get_cell.fif
@@ -11,9 +11,9 @@ swap // get seqno as int on top of stack
 type // print it to output
 cr // print endline
 
-<s dup 32 i@ // get seqno from cell
+<s dup 32 u@ // get seqno from cell
 swap ref@ // get ref on first cell
-<s 64 i@ // get message from second cell
+<s 64 u@ // get message from second cell
 swap // get seqno from cell to top
 
 ."🤗 Seqno as int from cell from " ^green ."GET" ^reset ." method is: " (dump) type cr
diff --git a/src/toncli/projects/wallet/fift/usage.fif b/src/toncli/projects/wallet/fift/usage.fif
index c4628f6..5924828 100644
--- a/src/toncli/projects/wallet/fift/usage.fif
+++ b/src/toncli/projects/wallet/fift/usage.fif
@@ -25,7 +25,7 @@ begin-options
     "Indicates the amount of extra currencies to be transfered" option-help
   "t" "--timeout" { parse-int =: timeout } short-long-option-arg
     "Sets expiration timeout in seconds (" timeout (.) $+ +" by default)" option-help
-  "B" "--body" { =: body-boc-file } short-long-option-arg
+  "B" "--body" { =: body-fift-file } short-long-option-arg
     "Sets the payload of the transfer message" option-help
   "C" "--comment" { =: comment } short-long-option-arg
     "Sets the comment to be sent in the transfer message" option-help
@@ -54,7 +54,7 @@ load-address
 ."INFO: 👀 Source wallet address = " 2dup 6 .Addr cr
 file-base +".pk" load-keypair nip constant wallet_pk
 
-def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond
+def? body-fift-file { @' body-fift-file include } { comment simple-transfer-body } cond
 constant body-cell
 
 ."INFO: 👋 Send " dest_addr 2dup bounce 7 + .Addr ." = "
diff --git a/src/toncli/projects/wallet/func/code.fc b/src/toncli/projects/wallet/func/code.func
similarity index 91%
rename from src/toncli/projects/wallet/func/code.fc
rename to src/toncli/projects/wallet/func/code.func
index 362896e..d410f14 100644
--- a/src/toncli/projects/wallet/func/code.fc
+++ b/src/toncli/projects/wallet/func/code.func
@@ -24,10 +24,10 @@
     }
 
     set_data(begin_cell()
-    .store_uint(stored_seqno + 1, 32)
-    .store_uint(stored_subwallet, 32)
-    .store_uint(public_key, 256)
-    .end_cell());
+        .store_uint(stored_seqno + 1, 32)
+        .store_uint(stored_subwallet, 32)
+        .store_uint(public_key, 256)
+        .end_cell());
 }
 
 ;; Get methods
@@ -46,7 +46,7 @@ int hello_world() method_id {
     ;; Ok now you need to add integer of your text
     ;; But soon TON Foundation will add string literals to func
     ;; And you will not need to do this
-    ;; hi as integer, try toncli tointeger hi
+    ;; hi as integer, try toncli topinteger hi
     return 26729;
 }
 
diff --git a/src/toncli/projects/wallet/project.yaml b/src/toncli/projects/wallet/project.yaml
index 94c7ab4..1e4f834 100644
--- a/src/toncli/projects/wallet/project.yaml
+++ b/src/toncli/projects/wallet/project.yaml
@@ -1,4 +1,4 @@
 contract:
   data: fift/data.fif
   func:
-    - func/code.fc
+    - func/code.func


Test patch:
diff --git a/src/toncli/lib/func-libs/stdlib.fc b/src/toncli/lib/func-libs/stdlib-tests.func
similarity index 98%
rename from src/toncli/lib/func-libs/stdlib.fc
rename to src/toncli/lib/func-libs/stdlib-tests.func
index 9ff0869..0431d32 100644
--- a/src/toncli/lib/func-libs/stdlib.fc
+++ b/src/toncli/lib/func-libs/stdlib-tests.func
@@ -205,4 +205,7 @@ int rand(int range) impure asm "RAND";
 int get_seed() impure asm "RANDSEED";
 int set_seed() impure asm "SETRAND";
 () randomize(int x) impure asm "ADDRAND";
-() randomize_lt() impure asm "LTIME" "ADDRAND";
\ No newline at end of file
+() randomize_lt() impure asm "LTIME" "ADDRAND";
+
+builder store_coins(builder b, int x) asm "STVARUINT16";
+(slice, int) load_coins(slice s) asm( -> 1 0) "LDVARUINT16";
\ No newline at end of file
diff --git a/src/toncli/lib/func-libs/tests-helpers.func b/src/toncli/lib/func-libs/tests-helpers.func
new file mode 100644
index 0000000..80acb76
--- /dev/null
+++ b/src/toncli/lib/func-libs/tests-helpers.func
@@ -0,0 +1,24 @@
+
+;; tuple creation helper
+forall X -> tuple unsafe_tuple(X x) asm "NOP";
+
+;; Toncli will automaticly download global_config
+;; And pass it to runvm (when running data functions)
+;; So you can get actual global config of network from get_config() function
+cell get_config() asm "CONFIGROOT";
+
+;; c7 config (if you don't know what it is - just use as is)
+tuple get_c7() inline method_id {
+    return unsafe_tuple([unsafe_tuple([
+        0x076ef1ea,           ;; magic
+        0,                    ;; actions
+        0,                    ;; msgs_sent
+        now(),                ;; unixtime
+        1,                    ;; block_lt
+        1,                    ;; trans_lt
+        239,                  ;; randseed
+        unsafe_tuple([1000000000, null()]),  ;; balance_remaining
+        null(),               ;; myself
+        get_config()          ;; global_config
+    ])]);
+}
\ No newline at end of file
diff --git a/src/toncli/modules/fift/run_test.fif b/src/toncli/modules/fift/fift_tests.fif.template.fif
similarity index 71%
rename from src/toncli/modules/fift/run_test.fif
rename to src/toncli/modules/fift/fift_tests.fif.template.fif
index 88cf0d9..8430855 100644
--- a/src/toncli/modules/fift/run_test.fif
+++ b/src/toncli/modules/fift/fift_tests.fif.template.fif
@@ -3,20 +3,11 @@
 "Asm.fif" include
 "Color.fif" include
 
-// todo: use GetOpt.fif
-// define usage comment
-{
-    ^yellow
-    ."usage: " $0 type ." script-path" cr
-    ."Run specific test on message.fif / code.fif / data.fif" cr
-    1 halt
-} : usage
+"{{ data_path }}" include
 
-// if less then 1 arguments print usage message
-$# 1 < ' usage if
 
 // load script-path
-$1 constant script-path
+constant data
 
 // TEST DEFINITION
 
@@ -34,7 +25,7 @@ $1 constant script-path
 } : test-is-builder
 
 // run script
-script-path include
+data
 
 // Run stack length test
 test-stack-depth
diff --git a/src/toncli/modules/fift/run_test.fif.template b/src/toncli/modules/fift/run_test.fif.template
new file mode 100644
index 0000000..ac82351
--- /dev/null
+++ b/src/toncli/modules/fift/run_test.fif.template
@@ -0,0 +1,153 @@
+"AsmTests.fif" include
+"Color.fif" include
+
+"{{ code_path }}" include
+constant code               // this is smc code
+drop  // drop functions defanition
+
+"{{ test_path }}" include     // it will return (@proclist, code cell)
+constant test_code         // save code cell as constant
+
+
+{{ verbose }} constant verbose
+
+// this is c7 that will be passed to test code
+0x076ef1ea           // magic
+0                    // actions
+0                    // msgs_sent
+now                  // unixtime
+1                    // block_lt
+1                    // trans_lt
+239                  // randseed
+1000000000 null pair // balance_remaining
+null                 // myself
+null                 // global_config
+10 tuple 1 tuple constant c7 // save as c7 cell
+
+
+// TODO: just use Lists.fif
+variable @tests_data       // here we will store all data functions
+variable @tests_names      // here we will store test names
+variable @tests            // here we will store all test functions
+
+variable @cnt        // here we will store tests list length
+@cnt 0!              // set as 0 by default
+
+// so in func main function is pre-defined with main name and method_id 0
+// we need this little trick to bypass problem, when user set other function name as method_id 0
+variable @is_zero_added
+@is_zero_added 0!
+
+// Add element to tuple in Box B with length B'
+// (x, B, B' -> )
+{   =: list_cnt
+    =: list
+    @' list @ dup null? not { @' list_cnt @ untuple } { drop } cond       // decomposes list if it is not null
+    @' list_cnt @ dup 0> { dup roll } { swap } cond                       // get item we want to add on top of stack
+    swap 1 +                                                              // update count
+    tuple @' list !                                                       // create and update tuple
+} : append
+
+{ @cnt @ 1 + @cnt ! } : next-cnt // increase count in box by 1
+{ @cnt @ 1 - @cnt ! } : prev-cnt
+
+{
+    dup null? not
+    @is_zero_added @ 1 = xor // fix main function duplication
+}                // check if not null
+{
+   unpair swap unpair            // get pair (function_name, method_id)
+   dup
+   2 mod                         // check is function test or data
+   0=  {                         // if data
+        dup 0= {  1 @is_zero_added ! } if
+        @tests_data @cnt append  // add data function method_id
+        drop                     // drop function name
+        next-cnt                 // finally update count by 1
+   } {                           // if test function
+        @tests @cnt append       // add test functuin method_id
+        @tests_names @cnt append // add test name
+   } cond
+} while // parse @proclist
+drop // remove other @proclist (or null)
+
+verbose 0>
+{   cr
+    ."INFO: 👸 Test data methods ids: " ^green @tests_data @ (dump) type ^reset cr
+    ."INFO: 🤳 Test methods ids: " ^green @tests @ (dump) type ^reset cr
+    ."INFO: 👼 Test names: " ^green @tests_names @ (dump) type ^reset cr
+    cr
+} if
+
+
+// ( -> test name, data f, test f, success)
+{
+    @tests_names @ @cnt @ untuple @cnt @ 1 - dup 0> { tuple @tests_names ! } { drop } cond // [0, 1, 2] => 0 [1, 2] => 0 (saved to box)
+    @tests_data @ @cnt @ untuple @cnt @ 1 - dup 0> { tuple @tests_data ! } { drop } cond
+    @tests @ @cnt @ untuple @cnt @ 1 - dup 0> { tuple @tests ! } { drop } cond
+    prev-cnt
+} : get-test
+
+{
+    swap // get function selector
+    test_code <s // load func code as slice
+    c7 // add c7 cell
+    0x11 runvmx // here we will get function selector, stack values, c4, c7, gas limit
+    0= not { abort"ERROR: 😱 Error running test data function, please double check it" } if
+    5 untuple
+    dup null? { drop 1000000000 } if
+    =: gas-limit
+    =: c7
+    =: c4
+    =: stack
+    =: function
+    =: test
+    =: test-name
+
+    verbose 0>
+    {
+        cr
+        ."INFO: Test [" ^green @' test-name type ^reset ."]: " cr
+        ."INFO:  Test function: [" ^green @' function (dump) type ^reset ."] " cr
+        ."INFO:  Test c7: [" ^green @' c7 (dump) type ^reset ."] " cr
+        ."INFO:  Test c4: [" ^green @' c4 (dump) type ^reset ."] " cr
+        ."INFO:  Test stack: [" ^green @' stack (dump) type ^reset ."] " cr
+        ."INFO:  Test gas-limit: [" ^green @' gas-limit (dump) type ^reset ."] " cr
+        cr
+    } if
+
+    @' stack explode // pass stack to runvm
+    drop // drop stack length
+    dup null? =: null_stored // little hack (check if we need to remove null)
+    @' function // function selector
+    code <s // load func code as slice
+    @' c4  // add c4 cell lodaded from lite-client
+    @' c7 // add c7 cell
+    @' gas-limit
+    0x3D runvmx  // Runvm
+
+    =: gas-used =: c5
+    =: c4  =: exit-code
+    @' null_stored { depth 1 - roll drop } if // if we store null priv. - need to remove
+    depth tuple =: stack
+
+    @' exit-code
+    @' c4
+    @' stack
+    @' c5
+    @' gas-used
+    @' test // test function selector
+    test_code <s // load func code as slice
+    c7 // add c7 cell
+    0x11 runvmx // here we will get function selector, stack values, c4, c7, gas limit
+
+    depth 1 >
+    { ."INFO: Test [" ^green @' test-name type ^reset ."] status: [" ^red ."FAIL" ^reset ."], code: [" ^cyan  (dump) type drop ^reset ."]" ." Gas used: [" ^green @' gas-used (dump) type ^reset ."]"  cr }
+    { ."INFO: Test [" ^green @' test-name type ^reset ."] status: [" ^green ."SUCCESS" ^reset ."]" ." Gas used: [" ^green @' gas-used (dump) type ^reset ."]" cr drop } cond
+
+} : run-test
+
+@cnt @
+{ dup 0> }
+{ drop get-test run-test @cnt @ }
+while  // run all tests
\ No newline at end of file
diff --git a/src/toncli/modules/tests/tests.py b/src/toncli/modules/tests/tests.py
new file mode 100644
index 0000000..ced4c35
--- /dev/null
+++ b/src/toncli/modules/tests/tests.py
@@ -0,0 +1,72 @@
+import os
+import tempfile
+from typing import List
+
+from toncli.modules.utils.fift.fift import Fift
+from toncli.modules.utils.system.log import logger
+from toncli.modules.utils.system.conf import getcwd, project_root
+from toncli.modules.utils.system.project_conf import ProjectConf
+from colorama import Fore, Style
+from toncli.modules.utils.func.commands import build as fift_build
+from jinja2 import FileSystemLoader, select_autoescape, Environment
+
+bl = Fore.CYAN
+rd = Fore.RED
+gr = Fore.GREEN
+rs = Style.RESET_ALL
+
+
+class TestsRunner:
+    def __init__(self):
+        self.project_config = ProjectConf(getcwd())
+
+    def run(self, contracts: List[str], verbose: int):
+        logger.info(f"🌈 Start tests")
+
+        if contracts is not None and len(contracts) > 0:
+            real_contracts = []
+
+            for item in contracts:
+                for config in self.project_config.contracts:
+                    if config.name == item:
+                        real_contracts.append(config)
+        else:
+            real_contracts = self.project_config.contracts
+
+        if not len(real_contracts):
+            logger.error(f"😥 No contracts from {contracts} are founded in project.yaml")
+
+        to_save_location = os.path.abspath(f"{getcwd()}/build")
+
+        # Build code
+        fift_build(getcwd(), contracts=real_contracts, cwd=getcwd(), use_tests_lib=True)
+
+        location = to_save_location.replace(getcwd(), '')
+        logger.info(f"🥌 Build {gr}successfully{rs}, check out {gr}.{location}{rs}")
+
+        for contract in real_contracts:
+            # Add info to Jinja template
+            render_kwargs = {
+                'code_path': contract.to_save_location,
+                'test_path': contract.to_save_tests_location,
+                'verbose': verbose
+            }
+
+            # Load template of transaction_debug
+            loader = FileSystemLoader(f"{project_root}/modules/fift")
+
+            env = Environment(
+                loader=loader,
+                autoescape=select_autoescape()
+            )
+
+            template = env.get_template("run_test.fif.template")
+
+            rendered = template.render(**render_kwargs)
+            temp_location: str = tempfile.mkstemp(suffix='.fif')[1]
+            with open(temp_location, 'w', encoding='utf-8') as f:
+                f.write(rendered)
+
+            # Run generated by jinja fift script
+            fift = Fift('run', args=[temp_location])  # prev_block])
+            fift.run()