diff --git a/3rdparty/crc32c_adler/CMakeLists.txt b/3rdparty/crc32c_adler/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..b444a2b87aa96f41186b91ac38f5558c73b22990
--- /dev/null
+++ b/3rdparty/crc32c_adler/CMakeLists.txt
@@ -0,0 +1,21 @@
+#
+#  DESCRIPTION: A miminal cmake script to be used to produce CRC32 Addler static library
+#
+#  AUTHOR: Ruslan R. Laishev
+#
+#  CREATION DATE: 14-NOV-2022
+#
+#  MODIFICATION HISTORY:
+#
+cmake_minimum_required(VERSION 3.10)
+project(crc32c_adler)
+
+set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall" )
+set( SRCS crc32c_adler.c  crc32c_adler.h)
+add_library(crc32c_adler  STATIC ${SRCS})
+
+target_link_libraries(crc32c_adler)
+
+if(NOT ANDROID)
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} pthread)
+endif()
diff --git a/3rdparty/iputils/iputils.h b/3rdparty/iputils/iputils.h
index 0330b548f1a23b5b677a4218683a933a169669e5..2ea8463d229e4acb4bba486941bfa0da45e54077 100644
--- a/3rdparty/iputils/iputils.h
+++ b/3rdparty/iputils/iputils.h
@@ -131,7 +131,7 @@ ping_handle_t* ping_handle_create(void);
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count);
+int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count, int wait);
 
 /**
  * Send ping for ipv6
diff --git a/3rdparty/iputils/ping.c b/3rdparty/iputils/ping.c
index a0a92de404de0d3c0c977fcd63f015f72d377848..63a8af4c27c415725260e06d3bded15bcff586e6 100644
--- a/3rdparty/iputils/ping.c
+++ b/3rdparty/iputils/ping.c
@@ -560,7 +560,7 @@ static int ping_main(ping_handle_t *a_ping_handle, int argc, char **argv)
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util_common(ping_handle_t *a_ping_handle, int type, const char *addr, int count)
+int ping_util_common(ping_handle_t *a_ping_handle, int type, const char *addr, int count, int wait)
 {
 
     /*
@@ -572,14 +572,15 @@ int ping_util_common(ping_handle_t *a_ping_handle, int type, const char *addr, i
      # sysctl net.ipv4.ping_group_range="1 65000"
      */
     a_ping_handle->ping_common.tsum = a_ping_handle->ping_common.ntransmitted = a_ping_handle->ping_common.nreceived = exiting = 0;
-    int argc = 3;
+    int argc = 4;
     const char *argv[argc];
     if(type != 4)
         argv[0] = "ping6";
     else
         argv[0] = "ping4";
     argv[1] = dap_strdup_printf("-c%d", count);
-    argv[2] = addr;
+    argv[2] = dap_strdup_printf("-w%d", wait);
+    argv[3] = addr;
     int status = ping_main(a_ping_handle, argc, (char**) argv);
     DAP_DELETE((char*) argv[1]);
     if(a_ping_handle->ping_common.ntransmitted >= 1 && a_ping_handle->ping_common.nreceived >= 1)
@@ -594,9 +595,9 @@ int ping_util_common(ping_handle_t *a_ping_handle, int type, const char *addr, i
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count)
+int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count, int wait)
 {
-    return ping_util_common(a_ping_handle, 4, addr, count);
+    return ping_util_common(a_ping_handle, 4, addr, count, wait);
 }
 
 /**
@@ -608,7 +609,7 @@ int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count)
  */
 int ping_util6(ping_handle_t *a_ping_handle, const char *addr, int count)
 {
-    return ping_util_common(a_ping_handle, 6, addr, count);
+    return ping_util_common(a_ping_handle, 6, addr, count, 10);
 }
 
 int ping4_run(ping_handle_t *a_ping_handle, int argc, char **argv, struct addrinfo *ai, socket_st *sock)
diff --git a/3rdparty/iputils/ping_common.c b/3rdparty/iputils/ping_common.c
index 566fdc755ee685ccff49f24f34d3450fb8590779..f35275b1f872e3680eb23c4e6e02546ffdb6c742 100644
--- a/3rdparty/iputils/ping_common.c
+++ b/3rdparty/iputils/ping_common.c
@@ -302,7 +302,7 @@ void fill(ping_handle_t *a_ping_handle, char *patp, unsigned char *packet, unsig
 
 static void sigexit(int signo __attribute__((__unused__)))
 {
-    //exiting = 1;
+    exiting = 1;
     //if(in_pr_addr)
     //    longjmp(pr_addr_jmp, 0);
 }
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 020c2f42cef08b3aacd952f45abc467e8d734bc1..c620d3a641013cf5b6a6a9d9612aa1ef840743b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,10 @@ set(CELLFRAME_SDK_NATIVE_VERSION "3.3-0")
 
 add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
 
+if (INSTALL_SDK)
+    set(INSTALL_DAP_SDK ON)
+endif()
+
 if(NOT DEFINED CELLFRAME_MODULES)
     include (dap-sdk/cmake/OS_Detection.cmake)
 
@@ -62,7 +66,7 @@ set(CELLFRAME_LIBS "")
 # Core libs from dap-sdk
 if (CELLFRAME_MODULES MATCHES "core")
     message("[+] Module 'core'")
-    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_core dap_app_cli dap_plugin dap_crypto m pthread)
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_core dap_app_cli dap_plugin dap_crypto m)
 endif()
 
 # General chain libs
@@ -75,7 +79,7 @@ endif()
 if (CELLFRAME_MODULES MATCHES "network")
     message("[+] Module 'network'")
     set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_io dap_json_rpc dap_enc_server dap_notify_srv dap_http_server dap_session
-        dap_stream dap_stream_ch dap_client dap_cli_server dap_stream_ch_chain dap_stream_ch_chain_net dap_chain_net dap_chain_net_srv dap_stream_ch_chain_voting dap_chain_mempool magic)
+        dap_stream dap_stream_ch dap_client dap_cli_server dap_stream_ch_chain dap_stream_ch_chain_net dap_chain_net dap_chain_net_srv dap_stream_ch_chain_voting dap_chain_mempool )
 endif()
 
 # Chain net services
@@ -191,3 +195,5 @@ endif()
 set(CELLFRAME_LIBS ${CELLFRAME_LIBS} crc32c_adler)
 
 target_link_libraries(${PROJECT_NAME} ${CELLFRAME_LIBS})
+
+
diff --git a/cellframe-sdk.pro b/cellframe-sdk.pro
new file mode 100644
index 0000000000000000000000000000000000000000..a9149d74a379b886b28b4780af3c9aeeb9498663
--- /dev/null
+++ b/cellframe-sdk.pro
@@ -0,0 +1,44 @@
+TEMPLATE = aux
+
+
+linux: !android {
+    sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.sh --target linux release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/
+}
+
+win32 {
+    contains(QMAKE_HOST.os, "Windows") {
+        sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.bat
+    }
+    else {
+        sdk_build.commands = "$$shell_path($$PWD/../cellframe-sdk/prod_build/build.sh)" --target windows release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/
+    }
+}
+
+android {
+    for (AABI, ANDROID_ABIS) {
+        message("Requested ABI: $$AABI")
+        sdk_build_$${AABI}.commands += $$PWD/../cellframe-sdk/prod_build/build.sh -b $$AABI --target android release -DANDROID_PLATFORM=android-21 -DANDROID_ABI=$$AABI -DANDROID_NATIVE_API_LEVEL=29 -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
+    }
+}
+
+mac {
+    
+    sdk_build.commands = $$PWD/../cellframe-sdk/prod_build/build.sh --target osx release -DINSTALL_SDK=1 -DCMAKE_INSTALL_PREFIX=/
+}
+
+QMAKE_EXTRA_TARGETS += sdk_build
+PRE_TARGETDEPS = sdk_build
+
+android {   
+    for (AABI, ANDROID_ABIS) {
+        
+        QMAKE_EXTRA_TARGETS += sdk_build_$${AABI}
+        PRE_TARGETDEPS += sdk_build_$${AABI}
+    }
+}
+
+sdk_targets.path = /
+sdk_targets.CONFIG += no_check_exist
+
+INSTALLS += sdk_targets
+
diff --git a/cmake/OS_Detection.cmake b/cmake/OS_Detection.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..16c323946d321c6c0fe44a046babe45527697c3f
--- /dev/null
+++ b/cmake/OS_Detection.cmake
@@ -0,0 +1,235 @@
+include_guard(GLOBAL)
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+    set(OS_TYPE_DESKTOP ON)
+    set(LINUX ON)
+    set(UNIX ON)
+    EXECUTE_PROCESS( COMMAND cat /etc/os-release COMMAND grep VERSION_CODENAME COMMAND sed s/VERSION_CODENAME=// COMMAND tr -d '\n' OUTPUT_VARIABLE L_DEBIAN_OS_NAME)
+    EXECUTE_PROCESS( COMMAND cat /etc/os-release COMMAND grep VERSION_ID COMMAND sed s/VERSION_ID=// COMMAND tr -d '\n' COMMAND sed s/\\x22// COMMAND sed s/\\x22// OUTPUT_VARIABLE L_DEBIAN_OS_VERSION)
+    SET(DEBIAN_OS_NAME "${L_DEBIAN_OS_NAME}")
+    SET(DEBIAN_OS_VERSION ${L_DEBIAN_OS_VERSION})
+    message("[ ] Debian OS ${DEBIAN_OS_VERSION} (${DEBIAN_OS_NAME})")
+# check if we're building natively on Android (TERMUX)
+    EXECUTE_PROCESS( COMMAND uname -o COMMAND tr -d '\n' OUTPUT_VARIABLE OPERATING_SYSTEM)
+    
+    execute_process (
+                    COMMAND bash -c "awk -F= '/^ID=/{print $2}' /etc/os-release |tr -d '\n' | tr -d '\"'"
+                    OUTPUT_VARIABLE DEBIAN_OS_RELEASE_NAME
+    )
+    
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
+    set(ANDROID ON)
+    set(UNIX ON)
+    set(LINUX OFF)
+    set(OS_TYPE_MOBILE ON)
+    message("[*] ANDROID build")
+    add_definitions(-DANDROID -DDAP_OS_ANDROID)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Win")
+    set(OS_TYPE_DESKTOP ON)
+endif()
+
+if((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (DAP_DEBUG))
+    message("[!] Debug build")
+    SET(DAP_DEBUG ON)
+else()
+    message("[!] Release build")
+    SET(DAP_RELEASE ON)
+    if((CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
+        message("[!] Debug symbols ON")
+        SET(DAP_DBG_INFO ON)
+    endif()
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL "8")
+  set(DEFAULT_BUILD_64 ON)
+else()
+  set(DEFAULT_BUILD_64 OFF)
+endif()
+option(BUILD_64 "Build for 64-bit? 'OFF' builds for 32-bit." ${DEFAULT_BUILD_64})
+
+if(BUILD_64)
+  set(ARCH_WIDTH "64")
+else()
+  set(ARCH_WIDTH "32")
+endif()
+message(STATUS "[*] Building for a ${ARCH_WIDTH}-bit system")
+
+if(UNIX)
+    add_definitions ("-DDAP_OS_UNIX")
+    if (APPLE)
+        
+        EXECUTE_PROCESS( COMMAND whoami COMMAND tr -d '\n' OUTPUT_VARIABLE L_USER)
+        EXECUTE_PROCESS( COMMAND echo -n /Users/${L_USER} OUTPUT_VARIABLE L_USERDIR_PATH)
+        set (USERDIR_PATH "${L_USERDIR_PATH}")
+        add_definitions ("-DDAP_OS_DARWIN -DDARWIN -DDAP_OS_BSD")
+        set(DARWIN ON)
+        set(BSD ON)
+        if (${_CMAKE_OSX_SYSROOT_PATH} MATCHES "MacOS")
+            set(MACOS ON)
+	    # on macOS "uname -m" returns the architecture (x86_64 or arm64)
+	    if (NOT DEFINED MACOS_ARCH)
+        
+            execute_process(
+            COMMAND uname -m
+            RESULT_VARIABLE result
+            OUTPUT_VARIABLE MACOS_ARCH
+            OUTPUT_STRIP_TRAILING_WHITESPACE
+            )
+        endif()
+            add_definitions("-DDAP_OS_MAC -DDAP_OS_MAC_ARCH=${MACOS_ARCH}")
+        elseif (${_CMAKE_OSX_SYSROOT_PATH} MATCHES "iOS")
+            set(IOS ON)
+            add_definitions("-DDAP_OS_IOS")
+        else()
+            set(MACOS ON)
+            add_definitions("-DDAP_OS_MAC -DDAP_OS_MAC_ARCH=${MACOS_ARCH}")
+        endif()
+    endif()
+    
+    if (${CMAKE_SYSTEM_NAME} MATCHES "BSD" )
+        add_definitions ("-DDAP_OS_BSD")
+        set(BSD ON)
+    endif()
+
+    if (${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
+        add_definitions ("-DDAP_OS_LINUX")
+    endif()
+    
+    set(CFLAGS_WARNINGS "-Wall -Wextra -Werror=sign-compare  -Wno-unused-command-line-argument -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter")
+    if (LINUX)
+        set(CCOPT_SYSTEM "")
+        set(LDOPT_SYSTEM "")
+        if(DAP_DEBUG)
+            set(_CCOPT "-DDAP_DEBUG ${CFLAGS_WARNINGS} -pg -g3 -ggdb -fno-eliminate-unused-debug-symbols -fno-strict-aliasing")
+            set(_LOPT "-pg")
+            if (DEFINED ENV{DAP_ASAN})
+                message("[!] Address Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common -O1")
+                set(_LOPT "${_LOPT} -fsanitize=address")
+            elseif(DEFINED ENV{DAP_MSAN})
+                if (CMAKE_C_COMPILER_ID MATCHES ".*[Cc][Ll][Aa][Nn][Gg].*")
+                    message("[!] Memory Sanitizer enabled")
+                    set(_CCOPT "${_CCOPT} -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -O2")
+                    set(_LOPT "${_LOPT} -fsanitize=memory -fPIE -pie")
+                else()
+                    message("[!] Memory Sanitizer is not available on this compiler")
+                endif()
+            elseif(DEFINED ENV{DAP_TSAN})
+                message("[!] Thread Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=thread")
+                set(_LOPT "${_LOPT} -fsanitize=thread")
+            elseif(DEFINED ENV{DAP_UBSAN})
+                message("[!] Undefined behaviour Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=undefined -fsanitize=bounds -fno-omit-frame-pointer")
+                set(_LOPT "${_LOPT} -fsanitize=undefined")
+            endif()
+            SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg")
+        else()
+            set(_CCOPT "${CFLAGS_WARNINGS} -fPIC -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -std=gnu11")
+            if (DEFINED ENV{DAP_ASAN})
+                message("[!] Address Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common -O2")
+                set(_LOPT "${_LOPT} -fsanitize=address")
+            elseif(DEFINED ENV{DAP_MSAN})
+                if (CMAKE_C_COMPILER_ID MATCHES ".*[Cc][Ll][Aa][Nn][Gg].*")
+                    message("[!] Memory Sanitizer enabled")
+                    set(_CCOPT "${_CCOPT} -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -O2")
+                    set(_LOPT "${_LOPT} -fsanitize=memory -fPIE -pie")
+                else()
+                    message("[!] Memory Sanitizer is not available on this compiler")
+                endif()
+            elseif(DEFINED ENV{DAP_TSAN})
+                message("[!] Thread Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=thread")
+                set(_LOPT "${_LOPT} -fsanitize=thread")
+            elseif(DEFINED ENV{DAP_UBSAN})
+                message("[!] Undefined behaviour Sanitizer enabled")
+                set(_CCOPT "${_CCOPT} -fsanitize=undefined -fsanitize=bounds -fno-omit-frame-pointer")
+                set(_LOPT "${_LOPT} -fsanitize=undefined")
+            else()
+                set(_CCOPT "${_CCOPT} -O3")
+                if(NOT DAP_DBG_INFO)
+                    set(_CCOPT "${_CCOPT} -Wl,--strip-all")
+                endif()
+            endif()
+        endif()
+    elseif (DARWIN)
+        set(CCOPT_SYSTEM "-L/usr/local/lib -L/opt/homebrew/lib -I/opt/homebrew/include -I/usr/local/include")
+        set(LDOPT_SYSTEM "-L/usr/local/lib -L/opt/homebrew/lib -lintl -flat_namespace")
+        set(CCFLAGS_COMMON "-std=c11 ${CFLAGS_WARNINGS}")
+        if(DAP_DEBUG)
+          set(_CCOPT "${CCOPT_SYSTEM} -DDAP_DEBUG ${CCFLAGS_COMMON} -g3 -ggdb -fno-eliminate-unused-debug-symbols -fno-strict-aliasing")
+          set(_LOPT "${LDOPT_SYSTEM}")
+          SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+        else()
+          set(_CCOPT "${CCOPT_SYSTEM} ${CCFLAGS_COMMON} -O3 -fPIC -fno-strict-aliasing -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections")
+          set(_LOPT "${LDOPT_SYSTEM}")
+          SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+        endif()
+    elseif(BSD)
+        set(CCOPT_SYSTEM "-L/usr/local/lib -I/usr/local/include")
+        set(LDOPT_SYSTEM "-L/usr/local/lib")
+        if(DAP_DEBUG)
+          set(_CCOPT "${CCOPT_SYSTEM} -DDAP_DEBUG ${CFLAGS_WARNINGS} -pg -g3 -ggdb -fno-eliminate-unused-debug-symbols -fno-strict-aliasing")
+          set(_LOPT "-pg ${LDOPT_SYSTEM} ")
+	  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg")
+        else()
+          set(_CCOPT "${CCOPT_SYSTEM} ${CFLAGS_WARNINGS} -O3 -fPIC -fno-strict-aliasing -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -std=gnu11")
+          set(_LOPT "${LDOPT_SYSTEM} ")
+          SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+        endif()
+    endif()
+
+    if (ANDROID)
+        if (ARCH_WIDTH MATCHES "32")
+            set(_CCOPT "${_CCOPT} -std=gnu11")
+        else()
+            set(_CCOPT "${_CCOPT} -fforce-enable-int128 -std=gnu11")
+        endif()
+        add_definitions ("-DDAP_OS_ANDROID")
+        add_definitions ("-DDAP_OS_LINUX")
+    endif()
+
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
+    set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${_LOPT}")
+
+endif()
+
+if(WIN32)
+    message(STATUS "[*] Building for Windows")
+    add_definitions ("-DDAP_OS_WINDOWS")
+    add_definitions ("-DUNDEBUG")
+    add_definitions ("-DWIN32")
+    add_definitions ("-D_WINDOWS")
+    add_definitions ("-D__WINDOWS__")
+    add_definitions ("-D_CRT_SECURE_NO_WARNINGS")
+    add_definitions ("-DCURL_STATICLIB")
+    add_definitions("-DHAVE_PREAD")
+    add_definitions("-DHAVE_MMAP")
+    add_definitions("-DHAVE_STRNDUP")
+    add_definitions("-DNGHTTP2_STATICLIB")
+    add_compile_definitions(WINVER=0x0600 _WIN32_WINNT=0x0600)
+    add_compile_definitions(__USE_MINGW_ANSI_STDIO=1)
+
+    set(CCOPT_SYSTEM "")
+    set(LDOPT_SYSTEM "")
+
+    if(DAP_DEBUG)
+      set(_CCOPT "-mconsole -static -std=gnu11 ${CFLAGS_WARNINGS} -g3 -ggdb -fno-strict-aliasing -fno-eliminate-unused-debug-symbols -pg")
+      set(_LOPT "-mconsole -static -pg")
+    else()
+      set(_CCOPT "-static -std=gnu11 ${CFLAGS_WARNINGS} -O3 -fPIC -fno-ident -ffast-math -fno-strict-aliasing -ftree-vectorize -mfpmath=sse -mmmx -msse2 -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections")
+      if(NOT DAP_DBG_INFO)
+          add_definitions ("-DNDEBUG")
+          set(_CCOPT "${_CCOPT} -Wl,--strip-all")
+      endif()
+    endif()
+
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT} ")
+    set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${_LOPT}")
+
+    include_directories(../../dap-sdk/3rdparty/uthash/src/)
+    include_directories(../../dap-sdk/3rdparty/json-c)
+    include_directories(3rdparty/wepoll/)
+    #include_directories(libdap-chain-net-srv-vpn/)
+endif()
diff --git a/dap-sdk b/dap-sdk
index 5410384db398c73f6667cf4aae3683790cf12126..79146c12e8a59a9fe77e6ae54997a70791f8f036 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 5410384db398c73f6667cf4aae3683790cf12126
+Subproject commit 79146c12e8a59a9fe77e6ae54997a70791f8f036
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index 5dd9d3350447247d1c12816351bcb7d25a8ee3e6..370a919ac37ef36837d2864bc196be379a1f5af2 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -1,3 +1,4 @@
+
 # Core
 if (CELLFRAME_MODULES MATCHES "core")
     add_subdirectory(common)
@@ -110,3 +111,8 @@ endif()
 if (CELLFRAME_MODULES MATCHES "srv-stake")
     add_subdirectory(service/stake)
 endif()
+
+# Unit tests
+if( BUILD_TESTS)
+    add_subdirectory(test)
+endif()
diff --git a/modules/chain/CMakeLists.txt b/modules/chain/CMakeLists.txt
index 22ff67a43028cc6d9faa74f537ee1ab49f903165..aad0b880f62506d46a56b1fb8c46548ade629565 100644
--- a/modules/chain/CMakeLists.txt
+++ b/modules/chain/CMakeLists.txt
@@ -18,3 +18,12 @@ target_link_libraries(${PROJECT_NAME} dap_chain_common dap_global_db dap_notify_
 target_include_directories(${PROJECT_NAME} INTERFACE . include/ ${GLIB_INCLUDE_DIRS})
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../dap-sdk/3rdparty/uthash/src)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/chain/
+        ARCHIVE DESTINATION lib/modules/chain/
+        PUBLIC_HEADER DESTINATION include/modules/chain/
+)
+endif()
\ No newline at end of file
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index decae85247d873dca50cc80f55a698f5100d62cd..d79f4448ca5cb97ff446c6383eed17f666531402 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -23,7 +23,7 @@
 */
 #include <sys/types.h>
 #include <dirent.h>
-#ifdef DAP_OS_LINUX
+#if defined(DAP_OS_LINUX) && !defined(DAP_OS_ANDROID)
 #include <stdc-predef.h>
 #endif
 #include <unistd.h>
diff --git a/modules/channel/chain-net-srv/CMakeLists.txt b/modules/channel/chain-net-srv/CMakeLists.txt
index e9c147d210b11713e39472c28ee466d62fe1089a..993f891e6557851315bfd8a989262036bf4c8656 100644
--- a/modules/channel/chain-net-srv/CMakeLists.txt
+++ b/modules/channel/chain-net-srv/CMakeLists.txt
@@ -10,3 +10,12 @@ target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain_common dap_c
 
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_STREAM_CH_CHAIN_NET_SRV_HDRS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/channel/chain-net-srv/
+        ARCHIVE DESTINATION lib/modules/channel/chain-net-srv/
+        PUBLIC_HEADER DESTINATION include/modules/channel/chain-net-srv/
+)
+endif()
\ No newline at end of file
diff --git a/modules/channel/chain-net/CMakeLists.txt b/modules/channel/chain-net/CMakeLists.txt
index 5972b985cc2fb8ce4bf225da11ce8ad00b02ee71..7f854714d53d638d37fe176b556289393ffa6846 100644
--- a/modules/channel/chain-net/CMakeLists.txt
+++ b/modules/channel/chain-net/CMakeLists.txt
@@ -12,3 +12,12 @@ target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_stream dap_stream_
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/uthash/src)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_STREAM_CH_CHAIN_NET_HDRS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/channel/chain-net/
+        ARCHIVE DESTINATION lib/modules/channel/chain-net/
+        PUBLIC_HEADER DESTINATION include/modules/channel/chain-net/
+)
+endif()
\ No newline at end of file
diff --git a/modules/channel/chain-voting/CMakeLists.txt b/modules/channel/chain-voting/CMakeLists.txt
index 39d888157b65eb06e7e4a7629ca0a7025aa585fd..f9efc7aa2bda54f5d0f283bf8f0e71ee8034ef8c 100644
--- a/modules/channel/chain-voting/CMakeLists.txt
+++ b/modules/channel/chain-voting/CMakeLists.txt
@@ -12,3 +12,12 @@ target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_stream dap_stream_
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/uthash/src)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_STREAM_CH_CHAIN_VOTING_HDRS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/channel/chain-voting/
+        ARCHIVE DESTINATION lib/modules/channel/chain-voting/
+        PUBLIC_HEADER DESTINATION include/modules/channel/chain-voting/
+)
+endif()
\ No newline at end of file
diff --git a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
index 8e683aeb087db0b3bd3050210f48d36e628c0b31..04088bc2697aa2a47422dae269b701ce2ef3132f 100644
--- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
+++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
@@ -69,6 +69,7 @@ static bool s_callback_pkt_in_call_all(dap_proc_thread_t UNUSED_ARG *a_thread, v
                                            &l_voting_pkt->hdr.data_hash, l_voting_pkt->data, l_voting_pkt->hdr.data_size);
         }
     }
+    DAP_DELETE(a_arg);
     return false;
 }
 
diff --git a/modules/channel/chain/CMakeLists.txt b/modules/channel/chain/CMakeLists.txt
index e60ffd18010f50339d283f37205df34f667e78d8..66387a0de86452ea111e52b2c7084cf96b0a5d95 100644
--- a/modules/channel/chain/CMakeLists.txt
+++ b/modules/channel/chain/CMakeLists.txt
@@ -11,3 +11,12 @@ target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_ne
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/uthash/src)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_STREAM_CH_CHAIN_HDRS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/channel/chain/
+        ARCHIVE DESTINATION lib/modules/channel/chain/
+        PUBLIC_HEADER DESTINATION include/modules/channel/chain/
+)
+endif()
\ No newline at end of file
diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c
index dba7f2ab16bc7939101523de4472d4eb9e1a261c..2e600f6f1a237c97eac9e2ec4a87466bfc380b5a 100644
--- a/modules/channel/chain/dap_stream_ch_chain.c
+++ b/modules/channel/chain/dap_stream_ch_chain.c
@@ -183,8 +183,11 @@ void dap_stream_ch_chain_deinit()
 void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
 {
     UNUSED(a_arg);
-    a_ch->internal = DAP_NEW_Z(dap_stream_ch_chain_t);
-    dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch);
+    if (!(a_ch->internal = DAP_NEW_Z(dap_stream_ch_chain_t))) {
+        log_it(L_CRITICAL, "Memory allocation error");
+        return;
+    };
+    dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch);
     l_ch_chain->_inheritor = a_ch;
     a_ch->stream->esocket->callbacks.write_finished_callback = s_stream_ch_io_complete;
 
@@ -260,6 +263,11 @@ static void s_sync_out_chains_first_worker_callback(dap_worker_t *a_worker, void
     }
 
     dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch);
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        s_sync_request_delete(l_sync_request);
+        return;
+    }
     if (l_ch_chain->state != CHAIN_STATE_UPDATE_CHAINS_REMOTE) {
         log_it(L_INFO, "Timeout fired before we sent the reply");
         s_sync_request_delete(l_sync_request);
@@ -298,6 +306,11 @@ static void s_sync_out_chains_last_worker_callback(dap_worker_t *a_worker, void
     }
 
     dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch);
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        s_sync_request_delete(l_sync_request);
+        return;
+    }
     l_ch_chain->request_atom_iter = l_sync_request->chain.request_atom_iter;
     // last packet
     dap_stream_ch_chain_sync_request_t l_request = {};
@@ -359,6 +372,13 @@ static void s_sync_out_gdb_first_worker_callback(dap_worker_t *a_worker, void *a
     }
 
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN( l_ch );
+
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        s_sync_request_delete(l_sync_request);
+        return;
+    }
+
     if (l_ch_chain->state != CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE) {
         log_it(L_INFO, "Timeout fired before we sent the reply");
         s_sync_request_delete(l_sync_request);
@@ -400,6 +420,11 @@ static void s_sync_out_gdb_last_worker_callback(dap_worker_t *a_worker, void *a_
     }
 
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN( l_ch );
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        s_sync_request_delete(l_sync_request);
+        return;
+    }
     s_sync_out_gdb_first_worker_callback(NULL,a_arg); // NULL to say callback not to delete request
 
     if (s_debug_more )
@@ -432,7 +457,11 @@ static bool s_sync_out_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a_ar
         return true;
     }
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch);
-
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        s_sync_request_delete(l_sync_request);
+        return true;
+    }
     int l_flags = 0;
     if (dap_chain_net_get_extra_gdb_group(l_net, l_sync_request->request.node_addr))
         l_flags |= F_DB_LOG_ADD_EXTRA_GROUPS;
@@ -490,6 +519,10 @@ static bool s_sync_update_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a
         log_it(L_INFO, "Client disconnected before we sent the reply");
         DAP_DELETE(l_sync_request);
         return true;
+    } else if (!DAP_STREAM_CH_CHAIN(l_ch)) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        DAP_DELETE(l_sync_request);
+        return true;
     }
 
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch);
@@ -698,6 +731,10 @@ static bool s_gdb_in_pkt_proc_set_raw_callback(dap_global_db_instance_t *a_dbi,
 struct sync_request *dap_stream_ch_chain_create_sync_request(dap_stream_ch_chain_pkt_t *a_chain_pkt, dap_stream_ch_t* a_ch)
 {
     dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch);
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        return NULL;
+    }
     struct sync_request *l_sync_request = DAP_NEW_Z(struct sync_request);
     if (!l_sync_request) {
         log_it(L_CRITICAL, "Memory allocation error");
@@ -716,6 +753,10 @@ struct sync_request *dap_stream_ch_chain_create_sync_request(dap_stream_ch_chain
 static void s_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, const char * a_err_string)
 {
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch);
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        return;
+    }
     s_ch_chain_go_idle(l_ch_chain);
     dap_stream_ch_chain_pkt_write_error_unsafe(a_ch, a_net_id, a_chain_id, a_cell_id, "%s", a_err_string);
 }
@@ -729,6 +770,11 @@ static bool s_chain_timer_callback(void *a_arg)
         return false;
     }
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch);
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        DAP_DELETE(a_arg);
+        return false;
+    }
     if (l_ch_chain->timer_shots++ >= DAP_SYNC_TICKS_PER_SECOND * DAP_CHAIN_NODE_SYNC_TIMEOUT) {
         if (!s_ch_chain_get_idle(l_ch_chain)) {
             s_ch_chain_go_idle(l_ch_chain);
@@ -1447,7 +1493,7 @@ static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg, int
     for (size_t i = 0; i < l_stream->channel_count; i++)
         if (l_stream->channel[i]->proc->id == DAP_STREAM_CH_ID)
             l_ch = l_stream->channel[i];
-    if (!l_ch)
+    if (!l_ch || !DAP_STREAM_CH_CHAIN(l_ch))
         return;
     if (a_arg) {
         struct chain_io_complete *l_arg = (struct chain_io_complete *)a_arg;
@@ -1494,6 +1540,11 @@ static void s_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type, u
 void s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg)
 {
     dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch);
+    if (!l_ch_chain) {
+        log_it(L_CRITICAL, "Channel without chain, dump it");
+        s_ch_chain_go_idle(l_ch_chain);
+        return;
+    }
     bool l_go_idle = false, l_was_sent_smth = false;
     switch (l_ch_chain->state) {
         // Update list of global DB records to remote
diff --git a/modules/common/CMakeLists.txt b/modules/common/CMakeLists.txt
index 2d9313b3809077b4992118c34fba7fa0d5f57fe7..1ff2e061d1cf28fbc02baff162a3cd0688f0d8ff 100644
--- a/modules/common/CMakeLists.txt
+++ b/modules/common/CMakeLists.txt
@@ -9,3 +9,13 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_COMMON_SRCS} ${DAP_CHAIN_COMMON_H
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_json-c)
 target_include_directories(${PROJECT_NAME} PUBLIC include/ )
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../dap-sdk/3rdparty/json-c)
+
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_COMMON_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/common/
+        ARCHIVE DESTINATION lib/modules/common/
+        PUBLIC_HEADER DESTINATION include/modules/common/
+)
+endif()
\ No newline at end of file
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 352b87901f7305335b97a9812b9e9c58ae7ee9d7..07118fbc49bf6453f03deb45853990b6c51e645e 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -554,7 +554,7 @@ dap_sign_t *dap_chain_datum_emission_get_signs(dap_chain_datum_token_emission_t
         log_it(L_CRITICAL, "Out of memory!");
         return NULL;
     }
-    *a_signs_count = MIN(l_count, a_emission->data.type_auth.signs_count);
+    *a_signs_count = dap_min(l_count, a_emission->data.type_auth.signs_count);
     memcpy(l_ret, a_emission->tsd_n_signs + a_emission->data.type_auth.tsd_total_size, l_actual_size);
     return l_ret;
 }
diff --git a/modules/consensus/block-poa/CMakeLists.txt b/modules/consensus/block-poa/CMakeLists.txt
index e6046505a9475a1139004f8fcd2e03a159fe2ec0..6d6eac00c8e59288c197a28b56ac871234cb4db8 100644
--- a/modules/consensus/block-poa/CMakeLists.txt
+++ b/modules/consensus/block-poa/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_CS_POA_SRCS} ${DAP_CHAIN_BL
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_blocks)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_BLOCK_CS_POA_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/block-poa/
+        ARCHIVE DESTINATION lib/modules/consensus/block-poa/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/block-poa/
+)
+endif()
\ No newline at end of file
diff --git a/modules/consensus/block-pos/CMakeLists.txt b/modules/consensus/block-pos/CMakeLists.txt
index 82db9813d05fe2dd9cff3c19cd96c8164462ed8e..dab434da2e84ba52be208f3da5cb7eddb74d4e3a 100644
--- a/modules/consensus/block-pos/CMakeLists.txt
+++ b/modules/consensus/block-pos/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_BLOCK_POS_SRCS} ${DAP_CHAIN_CS
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_blocks dap_chain_net_srv_stake)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_CS_BLOCK_POS_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/block-pos/
+        ARCHIVE DESTINATION lib/modules/consensus/block-pos/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/block-pos/
+)
+endif()
\ No newline at end of file
diff --git a/modules/consensus/block-pow/CMakeLists.txt b/modules/consensus/block-pow/CMakeLists.txt
index ec2ccd4bf15942e0fb9ee3de3cd8228a19980689..303aac749f0970a7f521f35259a909506945265e 100644
--- a/modules/consensus/block-pow/CMakeLists.txt
+++ b/modules/consensus/block-pow/CMakeLists.txt
@@ -10,3 +10,11 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_CS_POW_SRCS} ${DAP_CHAIN_BL
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_block )
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_BLOCK_CS_POW_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/block-pow/
+        ARCHIVE DESTINATION lib/modules/consensus/block-pow/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/block-pow/
+)
+endif()
\ No newline at end of file
diff --git a/modules/consensus/dag-poa/CMakeLists.txt b/modules/consensus/dag-poa/CMakeLists.txt
index 1fc52b9b33598f08ffb53f55bd2cd7a921d70988..7f8f02bcb1760aa4afc1bd565a5cb6169cb809d0 100644
--- a/modules/consensus/dag-poa/CMakeLists.txt
+++ b/modules/consensus/dag-poa/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_DAG_CS_POA_SRCS} ${DAP_CHAIN_DAG_
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_dag)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_DAG_CS_POA_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/dag-poa/
+        ARCHIVE DESTINATION lib/modules/consensus/dag-poa/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/dag-poa/ 
+        )
+endif()
\ No newline at end of file
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index 70c4b64b2610b70a66a0881720abebdd1624583e..3ed6b9dd31332e1d339d6d84f0817028784a1250 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -507,7 +507,7 @@ static void s_event_get_unique_mem_region(dap_chain_cs_dag_event_round_item_t *a
         dap_sign_t *l_sign = dap_chain_cs_dag_event_get_sign(l_event, a_round_item->event_size, n);
         size_t l_sign_size = 0;
         byte_t *l_sign_mem = dap_sign_get_sign(l_sign, &l_sign_size);
-        size_t l_mem_size = MIN(l_sign_size, DAP_CHAIN_POA_ROUND_FILTER_MEM_SIZE);
+        size_t l_mem_size = dap_min(l_sign_size, (size_t)DAP_CHAIN_POA_ROUND_FILTER_MEM_SIZE);
         for (size_t i = 0; i < l_mem_size; i++)
             a_mem_region[i] ^= l_sign_mem[i];
     }
@@ -616,7 +616,7 @@ static bool s_callback_round_event_to_chain_callback_get_round_item(dap_global_d
         char *l_event_hash_hex_str;
         dap_get_data_hash_str_static(l_new_atom, l_event_size, l_event_hash_hex_str);
         dap_chain_datum_t *l_datum = dap_chain_cs_dag_event_get_datum(l_new_atom, l_event_size);
-        l_dag->round_completed = MAX(l_new_atom->header.round_id, l_dag->round_current);
+        l_dag->round_completed = dap_max(l_new_atom->header.round_id, l_dag->round_current);
         int l_verify_datum = dap_chain_net_verify_datum_for_add(l_dag->chain, l_datum, &l_chosen_item->round_info.datum_hash);
         if (!l_verify_datum) {
             dap_chain_atom_verify_res_t l_res = l_dag->chain->callback_atom_add(l_dag->chain, l_new_atom, l_event_size);
diff --git a/modules/consensus/dag-pos/CMakeLists.txt b/modules/consensus/dag-pos/CMakeLists.txt
index 1e5cecca4333ca95873fbe794694732148f98ee3..fd5b077250fb91362675f0fd85369ea739b8cc44 100644
--- a/modules/consensus/dag-pos/CMakeLists.txt
+++ b/modules/consensus/dag-pos/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_DAG_POS_SRCS} ${DAP_CHAIN_CS_D
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_dag dap_chain_net_srv_stake)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_CS_DAG_POS_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/dag-pos/
+        ARCHIVE DESTINATION lib/modules/consensus/dag-pos/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/dag-pos/ 
+        )
+endif()
\ No newline at end of file
diff --git a/modules/consensus/esbocs/CMakeLists.txt b/modules/consensus/esbocs/CMakeLists.txt
index 8ba1a44ad9c583724c4e96f6eb5a34d07ef4f9e5..9c1ccd621372ddc6438b9d009ea8559ea453275f 100644
--- a/modules/consensus/esbocs/CMakeLists.txt
+++ b/modules/consensus/esbocs/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_ESBOCS_SRCS} ${DAP_CHAIN_CS_ESBOC
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_cs_blocks dap_stream_ch_chain_voting dap_chain_net_srv_stake)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_CS_ESBOCS_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/esbocs/
+        ARCHIVE DESTINATION lib/modules/consensus/esbocs/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/esbocs/ 
+        )
+endif()
\ No newline at end of file
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index c65014503051f650ec3d8a77ee5e8bb833430533..799426851a1a5362f3c3fcb4d3acfd644cd65065 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -665,7 +665,7 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session,
         }
 
         size_t l_consensus_optimum = (size_t)l_esbocs_pvt->min_validators_count * 2 - 1;
-        size_t l_need_vld_cnt = MIN(l_total_validators_count, l_consensus_optimum);
+        size_t l_need_vld_cnt = dap_min(l_total_validators_count, l_consensus_optimum);
 
         dap_pseudo_random_seed(*(uint256_t *)&a_session->cur_round.last_block_hash);
         for (uint64_t i = 0; i < a_skip_count * l_need_vld_cnt; i++)
@@ -1010,7 +1010,7 @@ static uint64_t s_session_calc_current_round_id(dap_chain_esbocs_session_t *a_se
             l_counter_max = l_id_candidates[i].counter;
             l_ret = l_id_candidates[i].id;
         } else if (l_id_candidates[i].counter == l_counter_max) // Choose maximum round ID
-            l_ret = MAX(l_ret, l_id_candidates[i].id);
+            l_ret = dap_max(l_ret, l_id_candidates[i].id);
     }
     return l_ret ? l_ret : a_session->cur_round.id;
 }
@@ -1025,7 +1025,7 @@ static int s_signs_sort_callback(dap_list_t *a_sign1, dap_list_t *a_sign2)
     }
     size_t  l_size1 = dap_sign_get_size(l_sign1),
             l_size2 = dap_sign_get_size(l_sign2),
-            l_size_min = MIN(l_size1, l_size2);
+            l_size_min = dap_min(l_size1, l_size2);
 
     int l_ret = memcmp(l_sign1, l_sign2, l_size_min);
     if (!l_ret) {
@@ -2610,6 +2610,13 @@ static int s_cli_esbocs(int a_argc, char ** a_argv, char **a_str_reply)
     if (dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index,a_argc,a_argv,a_str_reply,&l_chain,&l_chain_net)) {
         return -3;
     }
+    const char *l_chain_type = dap_chain_net_get_type(l_chain);
+    if (strcmp(l_chain_type, "esbocs")) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply,
+                        "Type of chain \"%s\" is not block. Chain with current consensus \"%s\" is not supported by this command",
+                        l_chain->name, l_chain_type);
+            return ret;
+    }
 
     if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, l_arg_index + 1, "set", NULL)) {
         dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str);
diff --git a/modules/dht/CMakeLists.txt b/modules/dht/CMakeLists.txt
index d1c37c570e7f993b87413a06d65d8b27488caa7a..73ce8aafa4a2259d2460962eae10e206d2ebbf3b 100644
--- a/modules/dht/CMakeLists.txt
+++ b/modules/dht/CMakeLists.txt
@@ -16,3 +16,11 @@ target_link_libraries(${PROJECT_NAME}  ${DAP_CHAIN_DHT_LIBS})
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_DHT_HDR}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/dht/
+        ARCHIVE DESTINATION lib/modules/dht/
+        PUBLIC_HEADER DESTINATION include/modules/dht/
+        )
+endif()
\ No newline at end of file
diff --git a/modules/mempool/CMakeLists.txt b/modules/mempool/CMakeLists.txt
index aaa39f7e84cb7544aed9caa3c9306607e16f5846..ce387cd752a5802f2125619dfb2db40251dd5868 100644
--- a/modules/mempool/CMakeLists.txt
+++ b/modules/mempool/CMakeLists.txt
@@ -10,3 +10,12 @@ target_link_libraries(${PROJECT_NAME} dap_http_server dap_client dap_chain_net d
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../dap-sdk/3rdparty/json-c)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_MEMPOOL_HDR}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/mempool/
+        ARCHIVE DESTINATION lib/modules/mempool/
+        PUBLIC_HEADER DESTINATION include/modules/mempool/
+        )
+endif()
\ No newline at end of file
diff --git a/modules/mining/CMakeLists.txt b/modules/mining/CMakeLists.txt
index 3967079cb0bf22b50675a75a753d6ad6c5aa0877..16c5b7ba417994029c65e11b0fe3d27e21c56ba8 100644
--- a/modules/mining/CMakeLists.txt
+++ b/modules/mining/CMakeLists.txt
@@ -21,3 +21,12 @@ if (${BUILD_DAP_CHAIN_CRYPTO_TESTS} MATCHES ON)
     enable_testing()
     add_subdirectory(test)
 endif()
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_CRYPTO_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/mining/
+        ARCHIVE DESTINATION lib/modules/mining/
+        PUBLIC_HEADER DESTINATION include/modules/mining/
+)
+endif()
\ No newline at end of file
diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt
index bc27aa577a109f6f19686661fde8901bada25d4d..97eceff79888dfdf561a62700236e0d2a1f95b76 100644
--- a/modules/net/CMakeLists.txt
+++ b/modules/net/CMakeLists.txt
@@ -43,3 +43,11 @@ if (!WIN32)
     target_include_directories(${PROJECT_NAME} PUBLIC ${IPUTILS_INCLUDE_DIRS})
 endif()
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/net/
+        ARCHIVE DESTINATION lib/modules/net/
+        PUBLIC_HEADER DESTINATION include/modules/net/
+)
+endif()
\ No newline at end of file
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 6478ed5be02713f5e5fafe1dce829a2164bacbfc..9e7b8576a915344bba7a104499a1c63eaa479de3 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -5108,7 +5108,37 @@ static dap_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, const
     return (l_tx_item) ? l_tx_item->tx : NULL;
 }
 
-
+ bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr)
+ {
+     dap_chain_datum_tx_t *l_tx;
+     l_tx = dap_ledger_tx_find_by_hash(a_ledger,a_tx_prev_hash);
+     dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL), *l_item;
+     if(!l_list_out_items)
+         return false;
+     bool l_ret = false;
+     DL_FOREACH(l_list_out_items, l_item) {
+         dap_chain_addr_t *l_dst_addr = NULL;
+         dap_chain_tx_item_type_t l_type = *(uint8_t*)l_item->data;
+         switch (l_type) {
+         case TX_ITEM_TYPE_OUT:
+             l_dst_addr = &((dap_chain_tx_out_t*)l_item->data)->addr;
+             break;
+         case TX_ITEM_TYPE_OUT_EXT:
+             l_dst_addr = &((dap_chain_tx_out_ext_t*)l_item->data)->addr;
+             break;
+         case TX_ITEM_TYPE_OUT_OLD:
+             l_dst_addr = &((dap_chain_tx_out_old_t*)l_item->data)->addr;
+         default:
+             break;
+         }
+         if(l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) {
+             l_ret = true;
+             break;
+         }
+     }
+     dap_list_free(l_list_out_items);
+     return l_ret;
+ }
 
 /**
  * Get the transaction in the cache by the public key that signed the transaction,
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 19e45cd19aacbd0b0c663f7001f417abbd4fd97b..c0c3f0115cbaa8e0f44ae7becf8a699c2625cb9f 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -810,18 +810,26 @@ static void s_net_balancer_link_prepare_success(dap_worker_t * a_worker, dap_cha
         }
         i++;
     }
+    struct net_link *l_free_link = NULL;
+    bool need_link = false;
+    pthread_mutex_lock(&PVT(l_net)->uplinks_mutex);
     if (l_balancer_request->link_replace_tries &&
             s_net_get_active_links_count(l_net) < PVT(l_net)->required_links_count) {
-        // Auto-start new link
+            // Auto-start new link
         dap_chain_net_state_t l_net_state = PVT(l_net)->state_target;
         if (l_net_state != NET_STATE_OFFLINE) {
-            struct net_link *l_free_link = s_get_free_link(l_net);
-            if (l_free_link)
-                s_net_link_start(l_net, l_free_link, PVT(l_net)->reconnect_delay);
-            else
-                s_new_balancer_link_request(l_net, l_balancer_request->link_replace_tries);
+            l_free_link = s_get_free_link(l_net);
+            need_link = true;
         }
+    }
+    pthread_mutex_unlock(&PVT(l_net)->uplinks_mutex);
 
+    // Auto-start new link
+    if(need_link){
+        if (l_free_link)
+            s_net_link_start(l_net, l_free_link, PVT(l_net)->reconnect_delay);
+        else
+            s_new_balancer_link_request(l_net, l_balancer_request->link_replace_tries);
     }
 
     if (!l_balancer_request->link_replace_tries)
@@ -921,9 +929,8 @@ static bool s_new_balancer_link_request(dap_chain_net_t *a_net, int a_link_repla
             node_cnt = l_link_full_node_list->count_node;
             int l_net_link_add = 0;
             size_t l_links_count = 0;
-            while(!l_net_link_add){
-                if(i >= node_cnt)
-                    break;
+            while(!l_net_link_add && i<node_cnt){
+
                 l_net_link_add = s_net_link_add(a_net, l_node_info + i);
                 switch (l_net_link_add) {
                 case 0:
@@ -1500,7 +1507,7 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply)
     // command 'list'
     const char * l_list_cmd = NULL;
 
-    if(dap_cli_server_cmd_find_option_val(argv, arg_index, MIN(argc, arg_index + 1), "list", &l_list_cmd) != 0 ) {
+    if(dap_cli_server_cmd_find_option_val(argv, arg_index, dap_min(argc, arg_index + 1), "list", &l_list_cmd) != 0 ) {
         dap_string_t *l_string_ret = dap_string_new("");
         if (dap_strcmp(l_list_cmd,"chains")==0){
             const char * l_net_str = NULL;
diff --git a/modules/net/dap_chain_net_node_list.c b/modules/net/dap_chain_net_node_list.c
index 74ee7e389c6988c5d518bc0336b3f9842edb7f7b..a6a280d1e8b0520be6121a36c8e5d16f9a6ab0b3 100644
--- a/modules/net/dap_chain_net_node_list.c
+++ b/modules/net/dap_chain_net_node_list.c
@@ -254,3 +254,43 @@ int dap_chain_net_node_list_request(dap_chain_net_t *a_net, dap_chain_node_info_
     s_node_list_request_deinit(l_node_list_request);
     return ret;
 }
+
+static void s_node_list_callback_notify(dap_store_obj_t *a_obj, void *a_arg)
+{
+    if (!a_arg || !a_obj || !a_obj->key)
+        return;
+    dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
+    assert(l_net);
+
+    if (!dap_strcmp(a_obj->group, l_net->pub.gdb_nodes)) {
+        if (a_obj->value && a_obj->type == DAP_GLOBAL_DB_OPTYPE_ADD) {
+            dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *)a_obj->value;
+            if(l_node_info->info.owner_addr.uint64 == 0){
+                log_it(L_NOTICE, "Node %s removed, there is not pinners", a_obj->key);
+                dap_global_db_del_sync(a_obj->group, a_obj->key);
+            } else {
+                char l_node_ipv4_str[INET_ADDRSTRLEN]={ '\0' }, l_node_ipv6_str[INET6_ADDRSTRLEN]={ '\0' };
+                inet_ntop(AF_INET, &l_node_info->hdr.ext_addr_v4, l_node_ipv4_str, INET_ADDRSTRLEN);
+                inet_ntop(AF_INET6, &l_node_info->hdr.ext_addr_v6, l_node_ipv6_str, INET6_ADDRSTRLEN);
+                char l_ts[128] = { '\0' };
+                dap_gbd_time_to_str_rfc822(l_ts, sizeof(l_ts), a_obj->timestamp);
+
+                log_it(L_MSG, "Add node "NODE_ADDR_FP_STR" %s %s, pinned by "NODE_ADDR_FP_STR" at %s",
+                                         NODE_ADDR_FP_ARGS_S(l_node_info->hdr.address),
+                                         l_node_ipv4_str, dap_itoa(l_node_info->hdr.ext_port),
+                                         NODE_ADDR_FP_ARGS_S(l_node_info->info.owner_addr),
+                                         l_ts);
+            }
+        }
+    }
+}
+
+int dap_chain_net_node_list_init()
+{
+    uint16_t l_net_count = 0;
+    dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count);
+    for (uint16_t i = 0; i < l_net_count; i++) {
+        dap_chain_net_add_nodelist_notify_callback(l_net_list[i], s_node_list_callback_notify, l_net_list[i]);
+    }
+    return 0;
+}
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index bd8f6d2caeebbf84d14629b093b638855ed1dae1..7cddc19615b750b4c12ddbcf55a1dcbeff259bf9 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -110,12 +110,15 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                     "node unban -net <net_name> -chain <chain_name> -certs <certs_name> [ -addr <node_address> | -ip <ip v4 or v6 address> ]\n"
                     "node banlist\n\n"
                                         );
+    #ifndef DAP_OS_ANDROID
     dap_cli_server_cmd_add ("ping", com_ping, "Send ICMP ECHO_REQUEST to network hosts",
             "ping [-c <count>] host\n");
     dap_cli_server_cmd_add ("traceroute", com_traceroute, "Print the hops and time of packets trace to network host",
             "traceroute host\n");
     dap_cli_server_cmd_add ("tracepath", com_tracepath,"Traces path to a network host along this path",
             "tracepath host\n");
+    #endif
+    
     dap_cli_server_cmd_add ("version", com_version, "Return software version",
                                         "version\n"
                                         "\tReturn version number\n"
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 977631d9189df51a330ba24ac7195f23c788c54b..30da15a32bda75e1460b137effc694d6e27461d5 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -35,7 +35,9 @@
 #include <assert.h>
 #include <ctype.h>
 #include <dirent.h>
+#ifndef DAP_OS_ANDROID
 #include <magic.h>
+#endif
 #include <sys/stat.h>
 
 #ifdef WIN32
@@ -603,21 +605,21 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
     int arg_index = 1;
     int cmd_name = CMD_NONE;
     // find 'cells' as first parameter only
-    if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "cells", NULL))
+    if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "cells", NULL))
         cmd_name = CMD_NAME_CELL;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "flush", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "flush", NULL))
         cmd_name = CMD_FLUSH;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "record", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "record", NULL))
             cmd_name = CMD_RECORD;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "write", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "write", NULL))
                 cmd_name = CMD_WRITE;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "read", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "read", NULL))
                 cmd_name = CMD_READ;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "delete", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "delete", NULL))
                 cmd_name = CMD_DELETE;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "drop_table", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "drop_table", NULL))
                 cmd_name = CMD_DROP;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "get_keys", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "get_keys", NULL))
             cmd_name = CMD_GET_KEYS;
 
     switch (cmd_name) {
@@ -649,7 +651,7 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
         int cmd_num = CMD_NONE;
         switch (cmd_name) {
             case CMD_NAME_CELL:
-                if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "add", NULL))
+                if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "add", NULL))
                         != 0) {
                     cmd_num = CMD_ADD;
                 }
@@ -721,15 +723,15 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
         int arg_index_n = ++arg_index;
         int l_subcmd;
         // Get value
-        if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "get", NULL))!= 0) {
+        if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "get", NULL))!= 0) {
             l_subcmd = SUMCMD_GET;
         }
         // Pin record
-        else if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "pin", NULL)) != 0) {
+        else if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "pin", NULL)) != 0) {
             l_subcmd = SUMCMD_PIN;
         }
         // Unpin record
-        else if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "unpin", NULL)) != 0) {
+        else if((arg_index_n = dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "unpin", NULL)) != 0) {
             l_subcmd = SUMCMD_UNPIN;
         }
         else{
@@ -1028,33 +1030,33 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply)
     };
     int arg_index = 1;
     int cmd_num = CMD_NONE;
-    if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "add", NULL)) {
+    if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "add", NULL)) {
         cmd_num = CMD_ADD;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "del", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "del", NULL)) {
         cmd_num = CMD_DEL;
     } // find  add parameter ('alias' or 'handshake')
-    else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "handshake", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "handshake", NULL)) {
         cmd_num = CMD_HANDSHAKE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "connect", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "connect", NULL)) {
         cmd_num = CMD_CONNECT;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "alias", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "alias", NULL)) {
         cmd_num = CMD_ALIAS;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "dump", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "dump", NULL)) {
         cmd_num = CMD_DUMP;
     }
-    else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "connections", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "connections", NULL)) {
         cmd_num = CMD_CONNECTIONS;
-    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index+1), "ban", NULL)) {
+    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index+1), "ban", NULL)) {
         cmd_num = CMD_BAN;
-    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index+1), "unban", NULL)) {
+    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index+1), "unban", NULL)) {
         cmd_num = CMD_UNBAN;
-    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index+1), "banlist", NULL)) {
+    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index+1), "banlist", NULL)) {
         cmd_num = CMD_BANLIST;
-    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "balancer", NULL)){
+    } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), "balancer", NULL)){
         cmd_num = CMD_BALANCER;
     }
     arg_index++;
@@ -1592,6 +1594,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply)
 }
 
 
+#ifndef DAP_OS_ANDROID
 /**
  * @brief Traceroute command
  * return 0 OK, -1 Err
@@ -1680,6 +1683,7 @@ int com_traceroute(int argc, char** argv, char **a_str_reply)
 }
 
 
+
 /**
  * @brief com_tracepath
  * Tracepath command
@@ -1777,12 +1781,13 @@ int com_ping(int a_argc, char**a_argv, char **a_str_reply)
 {
 #ifdef DAP_OS_LINUX
 
-    int n = 4;
+    int n = 4,w = 0;
     if (a_argc < 2) {
         dap_cli_server_cmd_set_reply_text(a_str_reply, "Host not specified");
         return -1;
     }
     const char *n_str = NULL;
+    const char *w_str = NULL;
     int argc_host = 1;
     int argc_start = 1;
     argc_start = dap_cli_server_cmd_find_option_val(a_argv, argc_start, a_argc, "-n", &n_str);
@@ -1796,13 +1801,22 @@ int com_ping(int a_argc, char**a_argv, char **a_str_reply)
             argc_host = argc_start + 1;
             n = (n_str) ? atoi(n_str) : 4;
         }
+        else
+        {
+            argc_start = dap_cli_server_cmd_find_option_val(a_argv, argc_start, a_argc, "-w", &w_str);
+            if(argc_start) {
+                argc_host = argc_start + 1;
+                n = 4;
+                w = (w_str) ? atoi(w_str) : 5;
+            }
+        }
     }
     if(n <= 1)
         n = 1;
     const char *addr = a_argv[argc_host];
     iputils_set_verbose();
     ping_handle_t *l_ping_handle = ping_handle_create();
-    int res = (addr) ? ping_util(l_ping_handle, addr, n) : -EADDRNOTAVAIL;
+    int res = (addr) ? ping_util(l_ping_handle, addr, n, w) : -EADDRNOTAVAIL;
     DAP_DELETE(l_ping_handle);
     if(res >= 0) {
         if(a_str_reply)
@@ -1835,6 +1849,7 @@ int com_ping(int a_argc, char**a_argv, char **a_str_reply)
     return -1;
 #endif
 }
+#endif /* !ANDROID (1582) */
 
 /**
  * @brief com_version
@@ -1914,17 +1929,17 @@ enum { CMD_NONE, CMD_WALLET_NEW, CMD_WALLET_LIST, CMD_WALLET_INFO, CMD_WALLET_AC
 int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
 
     // find  add parameter ('alias' or 'handshake')
-    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "new", NULL))
+    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "new", NULL))
         cmd_num = CMD_WALLET_NEW;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "list", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "list", NULL))
         cmd_num = CMD_WALLET_LIST;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "info", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "info", NULL))
         cmd_num = CMD_WALLET_INFO;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "activate", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "activate", NULL))
         cmd_num = CMD_WALLET_ACTIVATE;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "deactivate", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "deactivate", NULL))
         cmd_num = CMD_WALLET_DEACTIVATE;
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "convert", NULL))
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "convert", NULL))
         cmd_num = CMD_WALLET_CONVERT;
 
     l_arg_index++;
@@ -2712,39 +2727,6 @@ const char* s_tx_get_main_ticker(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_
     }
 }
 
-static bool dap_chain_mempool_find_addr_ledger(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr)
-{
-    dap_chain_datum_tx_t *l_tx;
-    l_tx = dap_ledger_tx_find_by_hash (a_ledger,a_tx_prev_hash);
-    dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL), *l_item;
-    if(!l_list_out_items)
-        return false;
-    bool l_ret = false;
-    DL_FOREACH(l_list_out_items, l_item) {
-        //assert(l_list_out->data);
-        dap_chain_addr_t *l_dst_addr = NULL;
-        dap_chain_tx_item_type_t l_type = *(uint8_t*)l_item->data;
-        switch (l_type) {
-        case TX_ITEM_TYPE_OUT:
-            l_dst_addr = &((dap_chain_tx_out_t*)l_item->data)->addr;
-            break;
-        case TX_ITEM_TYPE_OUT_EXT:
-            l_dst_addr = &((dap_chain_tx_out_ext_t*)l_item->data)->addr;
-            break;
-        case TX_ITEM_TYPE_OUT_OLD:
-            l_dst_addr = &((dap_chain_tx_out_old_t*)l_item->data)->addr;
-        default:
-            break;
-        }
-        if(l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) {
-            l_ret = true;
-            break;
-        }
-    }
-    dap_list_free(l_list_out_items);
-    return l_ret;
-}
-
 /**
  * @brief s_com_mempool_list_print_for_chain
  *
@@ -6009,7 +5991,7 @@ int com_stats(int argc, char **a_argv, char **a_str_reply)
     int arg_index = 1;
     int cmd_num = CMD_NONE;
     // find  add parameter ('cpu')
-    if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(argc, arg_index + 1), "cpu", NULL)) {
+    if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(argc, arg_index + 1), "cpu", NULL)) {
         cmd_num = CMD_STATS_CPU;
     }
     switch (cmd_num) {
@@ -6141,7 +6123,7 @@ int cmd_gdb_export(int a_argc, char **a_argv, char **a_str_reply)
         dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't open db directory");
         return -1;
     }
-    char l_path[MIN(strlen(l_gdb_path) + strlen(l_filename) + 12, MAX_PATH)];
+    char l_path[dap_min(strlen(l_gdb_path) + strlen(l_filename) + 12, (size_t)MAX_PATH)];
     memset(l_path, '\0', sizeof(l_path));
     snprintf(l_path, sizeof(l_path), "%s/%s.json", l_gdb_path, l_filename);
 
@@ -6214,6 +6196,7 @@ int cmd_gdb_export(int a_argc, char **a_argv, char **a_str_reply)
          json_object_put(l_json);
          return -1;
     }
+    dap_cli_server_cmd_set_reply_text(a_str_reply, "Global DB export in file %s", l_path);
     json_object_put(l_json);
     dap_cli_server_cmd_set_reply_text(a_str_reply, "Global DB export in file %s", l_path);
     return 0;
@@ -6521,7 +6504,7 @@ int com_signer(int a_argc, char **a_argv, char **a_str_reply)
 
     size_t l_len_opts = sizeof(l_opts) / sizeof(struct opts);
     for (size_t i = 0; i < l_len_opts; i++) {
-        if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), l_opts[i].name, NULL)) {
+        if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, dap_min(a_argc, arg_index + 1), l_opts[i].name, NULL)) {
             cmd_num = l_opts[i].cmd;
             break;
         }
@@ -7054,6 +7037,7 @@ static dap_tsd_t *s_alloc_metadata (const char *a_file, const int a_meta)
                 return dap_tsd_create_string(SIGNER_DATE, l_ctime);
             }
             break;
+        #ifndef DAP_OS_ANDROID
         case SIGNER_MIME_MAGIC:
             {
                 magic_t l_magic = magic_open(MAGIC_MIME);
@@ -7074,6 +7058,7 @@ static dap_tsd_t *s_alloc_metadata (const char *a_file, const int a_meta)
 
             }
             break;
+        #endif
         default:
             return NULL;
     }
diff --git a/modules/net/dap_chain_node_ping.c b/modules/net/dap_chain_node_ping.c
index 7bfc4acc011f124eabbb2c3e844c2ce852c36bf4..53efc69218474697c533e39fbe392546d99fc03c 100644
--- a/modules/net/dap_chain_node_ping.c
+++ b/modules/net/dap_chain_node_ping.c
@@ -240,7 +240,7 @@ static void* node_ping_background_proc(void *a_arg)
             continue;
         }
         int hops = 0, time_usec = 0;
-#ifdef DAP_OS_LINUX
+#if defined(DAP_OS_LINUX) && ! defined(DAP_OS_ANDROID)
         int res = traceroute_util(str_ip4, &hops, &time_usec);
 #endif
         if(l_min_hops>hops) {
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index e3639fbc66b38715895835c94d85bc8c1f1629ae..421c26e3d1ec80a72418cec86e0094c5bc1ee6c0 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -310,6 +310,8 @@ dap_hash_fast_t *dap_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_
 dap_chain_datum_tx_t* dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const char * a_token,
          const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash);
 
+bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr);
+
 // Get the transaction in the cache by the public key that signed the transaction, starting with a_tx_first_hash
 const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger,
         char *a_public_key, size_t a_public_key_size, dap_chain_hash_fast_t *a_tx_first_hash);
diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h
index f339ea1f7a4ec2f868dc744c66d4a462748f8ab0..4fa078bf0e8593c4fd5b6bf065e8742497035cff 100644
--- a/modules/net/include/dap_chain_node.h
+++ b/modules/net/include/dap_chain_node.h
@@ -43,7 +43,8 @@ typedef struct dap_chain_node_info {
     struct {
         uint64_t atoms_count; /* truncated alias len */
         uint32_t links_number;
-        byte_t other_info_for_future[240];
+        dap_chain_node_addr_t owner_addr;
+        byte_t other_info_for_future[232];
     } DAP_ALIGN_PACKED info;
     uint16_t alias_len;
     byte_t alias[];
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 8c7e8a55621cc76b21fc406305bd1ed5647a29c8..e4b97ef567babf57cefefdbb2d3cc091e6e5d707 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -43,6 +43,7 @@ int com_global_db(int a_argc,  char **a_argv, char **a_str_reply);
  */
 int com_node(int a_argc,  char **a_argv, char **a_str_reply);
 
+#ifndef DAP_OS_ANDROID
 /**
  * Traceroute command
  *
@@ -63,7 +64,7 @@ int com_tracepath(int a_argc,  char** argv, char **a_str_reply);
  * return 0 OK, -1 Err
  */
 int com_ping(int a_argc,  char** argv, char **a_str_reply);
-
+#endif
 /**
  * Help command
  */
diff --git a/modules/net/iputils/iputils.h b/modules/net/iputils/iputils.h
index e75981cb37cc30d5cf594421e2992b977cfbe561..b02fbe509a82df3075b0d98caafe5754749885f2 100644
--- a/modules/net/iputils/iputils.h
+++ b/modules/net/iputils/iputils.h
@@ -133,7 +133,7 @@ ping_handle_t* ping_handle_create(void);
  * @count number of packets to transmit
  * @return ping time in microsecond or -1 if error
  */
-int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count);
+int ping_util(ping_handle_t *a_ping_handle, const char *addr, int count, int wait);
 
 /**
  * Send ping for ipv6
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index 4950f4e3d56672a3c1bd3c46e25f1280572f8a83..17692b65ed02fbbbdf9b2c4510dd9adcd522f458 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -309,7 +309,7 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
                     else
                         dap_chain_net_srv_order_set_continent_region(&l_order, l_continent_num, l_region_str);
                     /*if(l_region_str) {
-                        strncpy(l_order->region, l_region_str, MIN(sizeof(l_order->region) - 1, strlen(l_region_str) + 1));
+                        strncpy(l_order->region, l_region_str, dap_min(sizeof(l_order->region) - 1, strlen(l_region_str) + 1));
                     }
                     if(l_continent_num>=0)
                         l_order->continent = l_continent_num;*/
diff --git a/modules/net/srv/dap_chain_net_srv_geoip.c b/modules/net/srv/dap_chain_net_srv_geoip.c
index 1320603d216ad2fbd3ee7ccd8cd50466fdceb4e9..1118073e4266c3c49b2c15a9380b1a787b2bf4ac 100644
--- a/modules/net/srv/dap_chain_net_srv_geoip.c
+++ b/modules/net/srv/dap_chain_net_srv_geoip.c
@@ -125,7 +125,7 @@ static int mmdb_get_value_str2(MMDB_lookup_result_s *a_result, const char *a_one
 	}
 	if (entry_data.has_data) {
 		if (entry_data.data_size > 0 && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
-			size_t l_size = MIN(a_out_str_size-1, entry_data.data_size);
+			size_t l_size = dap_min(a_out_str_size-1, entry_data.data_size);
 			strncpy(a_out_str, entry_data.utf8_string, l_size);
 			a_out_str[l_size] = 0;
 		} else
@@ -154,7 +154,7 @@ static int mmdb_get_value_str3(MMDB_lookup_result_s *a_result, const char *a_one
 	}
 	if (entry_data.has_data) {
 		if (entry_data.data_size > 0 && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
-			size_t l_size = MIN(a_out_str_size-1, entry_data.data_size);
+			size_t l_size = dap_min(a_out_str_size-1, entry_data.data_size);
 			strncpy(a_out_str, entry_data.utf8_string, l_size);
 			a_out_str[l_size] = 0;
 		} else
@@ -247,7 +247,7 @@ geoip_info_t *chain_net_geoip_get_ip_info_by_local_db(const char *a_ip_str, cons
 		return NULL;
 	}*/
 	int a = sizeof(l_ret->ip_str);
-	size_t l_size = MIN(dap_strlen(a_ip_str), sizeof(l_ret->ip_str));
+	size_t l_size = dap_min(dap_strlen(a_ip_str), sizeof(l_ret->ip_str));
 	l_ret->ip_str[l_size] = 0;
 	strncpy(l_ret->ip_str, a_ip_str, l_size);
 
diff --git a/modules/service/app-db/CMakeLists.txt b/modules/service/app-db/CMakeLists.txt
index b4126024c981d5b9f6626c906d6edac2744e9b5f..773ce29e3ce2c97e03b9c3bce9a08a36f93d336c 100644
--- a/modules/service/app-db/CMakeLists.txt
+++ b/modules/service/app-db/CMakeLists.txt
@@ -11,3 +11,11 @@ target_link_libraries(${PROJECT_NAME} dap_chain_net_srv dap_chain_net_srv_app)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_SRV_APP_DB_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/app-db/
+        ARCHIVE DESTINATION lib/modules/service/app-db/
+        PUBLIC_HEADER DESTINATION include/modules/service/app-db/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/app/CMakeLists.txt b/modules/service/app/CMakeLists.txt
index 6b36635629648f54fd13a8fd30add481f16115ff..eefc10c6dfa8dba683cbc185ec20f068e1e7f89a 100644
--- a/modules/service/app/CMakeLists.txt
+++ b/modules/service/app/CMakeLists.txt
@@ -10,3 +10,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_APP_SRCS} ${DAP_CHAIN_NET
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_SRV_APP_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/app/
+        ARCHIVE DESTINATION lib/modules/service/app/
+        PUBLIC_HEADER DESTINATION include/modules/service/app/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/datum/CMakeLists.txt b/modules/service/datum/CMakeLists.txt
index 6e00de0ce3e876786a73a34a57d6f97a93271783..8efb0756ab0d3509b458d41ee81f9a015aa21b46 100644
--- a/modules/service/datum/CMakeLists.txt
+++ b/modules/service/datum/CMakeLists.txt
@@ -11,3 +11,11 @@ target_link_libraries(${PROJECT_NAME} dap_chain_net_srv)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_SRV_DATUM_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/datum/
+        ARCHIVE DESTINATION lib/modules/service/datum/
+        PUBLIC_HEADER DESTINATION include/modules/service/datum/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/mining-pool/CMakeLists.txt b/modules/service/mining-pool/CMakeLists.txt
index e11093c3358acf2c27226ea4630ac0baba9d4aaa..ddfa6c982ee772edb7d2650752e560d67f2338d6 100644
--- a/modules/service/mining-pool/CMakeLists.txt
+++ b/modules/service/mining-pool/CMakeLists.txt
@@ -10,3 +10,11 @@ target_link_libraries(${PROJECT_NAME} dap_chain_net_srv dap_chain_net_srv_datum)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_SRV_DATUM_POOL_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/mining-pool/
+        ARCHIVE DESTINATION lib/modules/service/mining-pool/
+        PUBLIC_HEADER DESTINATION include/modules/service/mining-pool/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/stake/CMakeLists.txt b/modules/service/stake/CMakeLists.txt
index 30d7d45f2ee8f74721203eae0181ed51a3de1ff9..698441ef7c335f01ffc47359ec31d2ad1af66dc8 100644
--- a/modules/service/stake/CMakeLists.txt
+++ b/modules/service/stake/CMakeLists.txt
@@ -11,3 +11,12 @@ target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/json-c)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_SRV_STAKE_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/stake/
+        ARCHIVE DESTINATION lib/modules/service/stake/
+        PUBLIC_HEADER DESTINATION include/modules/service/stake/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/stake/dap_chain_net_srv_stake_lock.c b/modules/service/stake/dap_chain_net_srv_stake_lock.c
index 7a7f365a7315481b90a932fa7f0cb26a7516d09b..6a3d0ff3e01028f81a95b28b7be80c9da5d82269 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_lock.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c
@@ -701,9 +701,9 @@ static int s_cli_stake_lock(int a_argc, char **a_argv, char **a_str_reply)
     int				l_cmd_num		= CMD_NONE;
     dap_string_t	*output_line	= dap_string_new(NULL);
 
-    if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "hold", NULL))
+    if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "hold", NULL))
         l_cmd_num = CMD_HOLD;
-    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "take", NULL))
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "take", NULL))
         l_cmd_num = CMD_TAKE;
 
     switch (l_cmd_num) {
diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 44ecfb56b85d01e1b3c64774c17835f50e047f99..6a902ca33d5b04365004655b620314aaeeeb2b7c 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -988,16 +988,16 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
         CMD_NONE, CMD_CREATE, CMD_DECLARE, CMD_REMOVE, CMD_LIST, CMD_UPDATE
     };
     int l_cmd_num = CMD_NONE;
-    if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "create", NULL)) {
+    if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "create", NULL)) {
         l_cmd_num = CMD_CREATE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "remove", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "remove", NULL)) {
         l_cmd_num = CMD_REMOVE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "list", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "list", NULL)) {
         l_cmd_num = CMD_LIST;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "update", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "update", NULL)) {
         l_cmd_num = CMD_UPDATE;
     }
     int l_arg_index = a_arg_index + 1;
@@ -1443,7 +1443,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply)
     int l_arg_index = 1;
 
     const char * l_hash_out_type = NULL;
-    dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "-H", &l_hash_out_type);
+    dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "-H", &l_hash_out_type);
     if(!l_hash_out_type)
         l_hash_out_type = "base58";
     if(dap_strcmp(l_hash_out_type," hex") && dap_strcmp(l_hash_out_type, "base58")) {
@@ -1451,30 +1451,30 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply)
         return -1;
     }
     int l_cmd_num = CMD_NONE;
-    if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "order", NULL)) {
+    if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "order", NULL)) {
         l_cmd_num = CMD_ORDER;
     }
     // Create tx to freeze staker's funds and delete order
-    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "delegate", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "delegate", NULL)) {
         l_cmd_num = CMD_DELEGATE;
     }
     // Create tx to approve staker's funds freeze
-    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "approve", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "approve", NULL)) {
         l_cmd_num = CMD_APPROVE;
     }
     // Show the tx list with frozen staker funds
-    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "list", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "list", NULL)) {
         l_cmd_num = CMD_LIST;
     }
     // Return staker's funds
-    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "invalidate", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "invalidate", NULL)) {
         l_cmd_num = CMD_INVALIDATE;
     }
     // RSetss stake minimum value
-    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "min_value", NULL)) {
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "min_value", NULL)) {
         l_cmd_num = CMD_MIN_VALUE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "check", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "check", NULL)) {
         l_cmd_num = CMD_CHECK;
     }
 
diff --git a/modules/service/vpn/CMakeLists.txt b/modules/service/vpn/CMakeLists.txt
index 2109c3b797b86263e45d4db5bb392ce014bdff83..04be24a936012b5d8c5276799184d26c8aa01eb4 100644
--- a/modules/service/vpn/CMakeLists.txt
+++ b/modules/service/vpn/CMakeLists.txt
@@ -21,3 +21,11 @@ add_definitions("-DDAP_TUN_IN_WORKER")
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_NET_SRV_VPN_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/vpn/
+        ARCHIVE DESTINATION lib/modules/service/vpn/
+        PUBLIC_HEADER DESTINATION include/modules/service/vpn/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
index 2850a2b406ca6b0521f038bdc13a6f299a2fb096..0e1f171d23710f4a51cf2843c211314ae8069cd5 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
@@ -114,21 +114,21 @@ int com_vpn_client(int a_argc, char ** a_argv, char **a_str_reply)
         return -2;
 
     int cmd_num = CMD_NONE;
-    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "init", NULL)) {
+    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "init", NULL)) {
         cmd_num = CMD_INIT;
     }
-    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "start", NULL)) {
+    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "start", NULL)) {
             cmd_num = CMD_START;
         }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "stop", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "stop", NULL)) {
         cmd_num = CMD_STOP;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "status", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "status", NULL)) {
         cmd_num = CMD_STATUS;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "check", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "check", NULL)) {
         cmd_num = CMD_CHECK;
-        if(dap_cli_server_cmd_find_option_val(a_argv, MIN(a_argc, l_arg_index + 1), MIN(a_argc, l_arg_index + 2), "result", NULL)) {
+        if(dap_cli_server_cmd_find_option_val(a_argv, dap_min(a_argc, l_arg_index + 1), dap_min(a_argc, l_arg_index + 2), "result", NULL)) {
                 cmd_num = CMD_CHECK_RESULT;
             }
     }
diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c
index 2faaff226ab896745526e5451c5645f06bad69d5..f9278506e8d93b569dbcafd653b5f391d4ae7cf7 100644
--- a/modules/service/vpn/dap_chain_net_vpn_client.c
+++ b/modules/service/vpn/dap_chain_net_vpn_client.c
@@ -558,7 +558,7 @@ int dap_chain_net_vpn_client_check(dap_chain_net_t *a_net, const char *a_ipv4_st
             randombytes(l_request->data, a_data_size_to_send);
             dap_hash_fast(l_request->data, l_request->data_size, &l_request->data_hash);
             if(a_ipv4_str)
-                memcpy(l_request->ip_recv, a_ipv4_str, MIN(sizeof(l_request->ip_recv), strlen(a_ipv4_str)));
+                memcpy(l_request->ip_recv, a_ipv4_str, dap_min(sizeof(l_request->ip_recv), strlen(a_ipv4_str)));
             l_request->time_connect_ms = l_dtime_connect_ms;
             l_request->send_time1 = dap_nanotime_now();
             size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t);
diff --git a/modules/service/vpn/dap_chain_net_vpn_client_tun.c b/modules/service/vpn/dap_chain_net_vpn_client_tun.c
index 9b7b416466d5680fe231d89455cdadcd67a19467..ffd219b19f1772c140bdf1a83740d3255a9d31b5 100644
--- a/modules/service/vpn/dap_chain_net_vpn_client_tun.c
+++ b/modules/service/vpn/dap_chain_net_vpn_client_tun.c
@@ -379,7 +379,7 @@ static void m_client_tun_read(dap_events_socket_t * a_es, void * arg)
     dap_stream_ch_t* l_ch = dap_chain_net_vpn_client_get_stream_ch();
     size_t l_read_bytes = 0, l_shift = 0;
 
-    for (; (l_read_bytes = MIN(a_es->buf_in_size, TUN_MTU)); a_es->buf_in_size -= l_read_bytes, l_shift += l_read_bytes) {
+    for (; (l_read_bytes = dap_min(a_es->buf_in_size, (size_t)TUN_MTU)); a_es->buf_in_size -= l_read_bytes, l_shift += l_read_bytes) {
         if (!l_ch) {
             struct in_addr in_daddr, in_saddr;
 #ifdef DAP_OS_LINUX
diff --git a/modules/service/xchange/CMakeLists.txt b/modules/service/xchange/CMakeLists.txt
index e8184d32bbd2c5651173e8a57d8a4721ff03219e..0514c862d4beecdb75784fcd616ff8d54802b95f 100644
--- a/modules/service/xchange/CMakeLists.txt
+++ b/modules/service/xchange/CMakeLists.txt
@@ -10,3 +10,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_SRV_XCHANGE_SRCS} ${DAP_SRV_XCHANGE_HEA
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_net dap_chain_net_srv)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_SRV_XCHANGE_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/service/xchange/
+        ARCHIVE DESTINATION lib/modules/service/xchange/
+        PUBLIC_HEADER DESTINATION include/modules/service/xchange/
+)
+endif()
\ No newline at end of file
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 62c029e9cb9c0a4de4cc4740199d0d85f4b6bffe..97c2df6746bf66244b7a17d8347b1adf77222d5d 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -981,16 +981,19 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
         CMD_NONE, CMD_CREATE, CMD_REMOVE, CMD_UPDATE, CMD_HISTORY, CMD_STATUS
     };
     int l_cmd_num = CMD_NONE;
-    if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "create", NULL)) {
+    if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "create", NULL)) {
         l_cmd_num = CMD_CREATE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "remove", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "remove", NULL)) {
         l_cmd_num = CMD_REMOVE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "history", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "update", NULL)) {
+        l_cmd_num = CMD_UPDATE;
+    }
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "history", NULL)) {
         l_cmd_num = CMD_HISTORY;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "status", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, dap_min(a_argc, a_arg_index + 1), "status", NULL)) {
         l_cmd_num = CMD_STATUS;
     }
     int l_arg_index = a_arg_index + 1;
@@ -1636,25 +1639,25 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply)
     int l_arg_index = 1, l_cmd_num = CMD_NONE;
     bool l_rc;
 
-    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "order", NULL)) {
+    if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "order", NULL)) {
         l_cmd_num = CMD_ORDER;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "orders", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "orders", NULL)) {
         l_cmd_num = CMD_ORDERS;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "purchase", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "purchase", NULL)) {
         l_cmd_num = CMD_PURCHASE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "enable", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "enable", NULL)) {
         l_cmd_num = CMD_ENABLE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "disable", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "disable", NULL)) {
         l_cmd_num = CMD_DISABLE;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "tx_list", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "tx_list", NULL)) {
         l_cmd_num = CMD_TX_LIST;
     }
-    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, MIN(a_argc, l_arg_index + 1), "token_pair", NULL)) {
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "token_pair", NULL)) {
         l_cmd_num = CMD_TOKEN_PAIR;
     }
 
diff --git a/modules/type/blocks/CMakeLists.txt b/modules/type/blocks/CMakeLists.txt
index a4bdd1bbad8c732f94d5ee79cd9d63be0f573c0d..32900e1ceca6f6b3b31c58ea195193eabb766f9b 100644
--- a/modules/type/blocks/CMakeLists.txt
+++ b/modules/type/blocks/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_BLOCK_SRCS} ${DAP_CHAIN_BLOCK_HEA
 target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_cli_server dap_chain_net)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_BLOCK_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/type/blocks/
+        ARCHIVE DESTINATION lib/modules/type/blocks/
+        PUBLIC_HEADER DESTINATION include/modules/type/blocks/
+)
+endif()
\ No newline at end of file
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 160dcde7bd19c6588fb077534ff9742c1e0c014c..5ae67b39dae1e6d901d53134be6fdca184396c34 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -1915,7 +1915,7 @@ static uint256_t s_callback_calc_reward(dap_chain_t *a_chain, dap_hash_fast_t *a
     assert(l_block_cache);
     l_block = l_block_cache->block;
     assert(l_block);
-    dap_time_t l_time_diff = l_block_time - MAX(l_block->hdr.ts_created, DAP_REWARD_INIT_TIMESTAMP);
+    dap_time_t l_time_diff = l_block_time - dap_max(l_block->hdr.ts_created, DAP_REWARD_INIT_TIMESTAMP);
     MULT_256_256(l_ret, GET_256_FROM_64(l_time_diff), &l_ret);
     DIV_256(l_ret, GET_256_FROM_64(s_block_timediff_unit_size * l_signs_count), &l_ret);
     return l_ret;
diff --git a/modules/type/dag/CMakeLists.txt b/modules/type/dag/CMakeLists.txt
index dc1d80326d52f7600d8ada0b6702b9b2b330b22c..3bd7a2227a0dd56d92fd9934a1a77363b2c982f8 100644
--- a/modules/type/dag/CMakeLists.txt
+++ b/modules/type/dag/CMakeLists.txt
@@ -9,3 +9,12 @@ target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_ne
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
 target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../dap-sdk/3rdparty/uthash/src)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_DAG_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/type/dag/
+        ARCHIVE DESTINATION lib/modules/type/dag/
+        PUBLIC_HEADER DESTINATION include/modules/type/dag/
+)
+endif()
\ No newline at end of file
diff --git a/modules/type/none/CMakeLists.txt b/modules/type/none/CMakeLists.txt
index cd45b3e9cdb5dfb5e77b5ce5aaf5d2c93a5068db..81dbb6a8f6559c9aed1934d6f9cf3e899248ec50 100644
--- a/modules/type/none/CMakeLists.txt
+++ b/modules/type/none/CMakeLists.txt
@@ -9,3 +9,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_NO_CONSENSUS_SRC} ${DAP_CHAIN_
 target_link_libraries(${PROJECT_NAME} dap_core dap_chain dap_global_db dap_chain_mempool dap_chain_net)
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_CS_NO_CONSENSUS_HDR}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/consensus/none/
+        ARCHIVE DESTINATION lib/modules/consensus/none/
+        PUBLIC_HEADER DESTINATION include/modules/consensus/none/ 
+        )
+endif()
\ No newline at end of file
diff --git a/modules/wallet/CMakeLists.txt b/modules/wallet/CMakeLists.txt
index 4bcf36d090e687648d8214d0eb4358c3d5d8031b..0b4cc30c885bdcf94b5a03d7fcd24d8be55ed516 100644
--- a/modules/wallet/CMakeLists.txt
+++ b/modules/wallet/CMakeLists.txt
@@ -14,3 +14,12 @@ else()
 endif()
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
+
+if (INSTALL_SDK)
+set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_WALLET_HEADERS}")
+INSTALL(TARGETS ${PROJECT_NAME} 
+        LIBRARY DESTINATION lib/modules/wallet/
+        ARCHIVE DESTINATION lib/modules/wallet/
+        PUBLIC_HEADER DESTINATION include/modules/wallet/
+)
+endif()
\ No newline at end of file
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index 9316c4eed5614ed5de8f780a68820bdc60a533cf..900fb942a484ecffbb317c16015dac6f9035bbeb 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -60,6 +60,14 @@
 #include "crc32c_adler.h"
 #include "dap_chain_ledger.h"
 
+#define __USE_GNU
+
+#if defined(__USE_BSD) || defined(__USE_GNU)
+#define S_IREAD S_IRUSR
+#define S_IWRITE S_IWUSR
+#define S_IEXEC S_IXUSR
+#endif
+
 #define LOG_TAG "dap_chain_wallet"
 
 #ifndef DAP_OS_WINDOWS                                    /* An argument for open()/create() */
diff --git a/prod_build/build.sh b/prod_build/build.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3150886bfa9480741c59673af1bd3d7d6946ff5b
--- /dev/null
+++ b/prod_build/build.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+MHERE="$DIR"
+
+
+export SOURCES=${MHERE}/../
+
+NAME_OUT="$(uname -s)"
+case "${NAME_OUT}" in
+    Linux*)     MACHINE=Linux;;
+    Darwin*)    MACHINE=Mac;;
+    CYGWIN*)    MACHINE=Cygwin;;
+    MINGW*)     MACHINE=MinGw;;
+    MSYS_NT*)   MACHINE=Git;;
+    *)          MACHINE="UNKNOWN:${NAME_OUT}"
+esac
+
+
+
+#validate input params
+. ${MHERE}/validate.sh
+
+Help()
+{
+   echo "cellframe-sdk build"
+   echo "Usage: build.sh [--target ${TARGETS}] [${BUILD_TYPES}]  [OPTIONS]"
+   echo "options:   -DWHATEVER=ANYTHING will be passed to cmake as defines"
+   echo
+}
+
+POSITIONAL_ARGS=()
+
+while [[ $# -gt 0 ]]; do
+  case $1 in
+    -h|--help)
+      Help
+      shift # past argument
+      shift # past value
+      ;;
+    -t|--target)
+      TARGET="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    -b|--bpfx)
+      BUILD_POSTFIX="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    *)
+      POSITIONAL_ARGS+=("$1") # save positional arg
+      shift # past argument
+      ;;
+  esac
+done
+
+set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
+
+BUILD_TYPE="${1:-release}"
+BUILD_OPTIONS="${@:2}"
+
+
+DEFAULT_TARGET="linux"
+if [ "$MACHINE" == "Mac" ]
+then
+  DEFAULT_TARGET="osx"
+fi
+
+if [ "$MACHINE" == "Linux" ]
+then
+  DEFAULT_TARGET="linux"
+fi
+
+if [ "$MACHINE" == "Git" ]
+then
+  DEFAULT_TARGET="windows"
+fi
+
+echo "Host machin is $MACHINE"
+BUILD_TARGET="${TARGET:-$DEFAULT_TARGET}"
+BUILD_DIR=${PWD}/build_${BUILD_TARGET}_${BUILD_TYPE}/$BUILD_POSTFIX/
+
+VALIDATE_TARGET $TARGET
+VALIDATE_BUILD_TYPE $BUILD_TYPE
+
+#append qmake debug\release qmake options for this
+if [ "${BUILD_TYPE}" = "debug" ]; then
+    BUILD_OPTIONS[${#BUILD_OPTIONS[@]}]="-DCMAKE_BUILD_TYPE=Debug"
+else
+    if [ "${BUILD_TYPE}" = "rwd" ]; then
+      BUILD_OPTIONS[${#BUILD_OPTIONS[@]}]="-DCMAKE_BUILD_TYPE=RelWithDebInfo"
+    else
+      BUILD_OPTIONS[${#BUILD_OPTIONS[@]}]="-DCMAKE_BUILD_TYPE=Release"
+    fi
+fi
+
+. ${HERE}/targets/${BUILD_TARGET}.sh
+
+#all base logic from here
+mkdir -p ${BUILD_DIR}/build
+mkdir -p ${BUILD_DIR}/dist
+
+if [ "$MACHINE" != "Mac" ]
+then
+  NPROC="$(nproc)"
+else
+  NPROC="$(sysctl -n hw.ncpu)"
+fi
+
+echo "Build [${BUILD_TYPE}] binaries for [$BUILD_TARGET] in [${BUILD_DIR}] on $NPROC threads"
+echo "with options: [${BUILD_OPTIONS[@]}]"
+
+cd ${BUILD_DIR}/build/
+
+#debug out
+pwd
+echo "${CMAKE[@]} ${MHERE}/../  ${BUILD_OPTIONS[@]}"
+#echo $HERE
+export INSTALL_ROOT=${BUILD_DIR}/dist
+"${CMAKE[@]}" ${MHERE}/../ ${BUILD_OPTIONS[@]}  
+"${MAKE[@]}" #-j $NPROC
+"${MAKE[@]}" install DESTDIR=${INSTALL_ROOT}
diff --git a/prod_build/pack.sh b/prod_build/pack.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2eaadcd4a2d7cdbdff4d4b603921b1ca533177a3
--- /dev/null
+++ b/prod_build/pack.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+
+export SOURCES=${HERE}/../
+
+containsElement () {
+  local e match="$1"
+  shift
+  for e; do [[ "$e" == "$match" ]] && return 0; done
+  return 1
+}
+
+echo "Pack for cellframe-sdk not implemented yet" && exit 127
+
+Help()
+{
+   echo "cellframe-sdk pack"
+   echo "Usage: pack.sh [--target linux | windows | android] [release | debug]"
+}
+
+POSITIONAL_ARGS=()
+
+while [[ $# -gt 0 ]]; do
+  case $1 in
+    -h|--help)
+      Help
+      shift # past argument
+      shift # past value
+      ;;
+    -t|--target)
+      TARGET="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    *)
+      POSITIONAL_ARGS+=("$1") # save positional arg
+      shift # past argument
+      ;;
+  esac
+done
+
+set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
+
+#all base logic from here
+
+
+BUILD_TYPE="${1:-release}"
+BUILD_OPTIONS="${@:2}"
+
+BUILD_TARGET="${TARGET:-linux}"
+
+
+#validate input params
+. ${HERE}/validate.sh
+VALIDATE_TARGET $TARGET
+VALIDATE_BUILD_TYPE $BUILD_TYPE
+
+DIST_DIR=${PWD}/build_${BUILD_TARGET}_${BUILD_TYPE}/dist
+BUILD_DIR=${PWD}/build_${BUILD_TARGET}_${BUILD_TYPE}/build
+OUT_DIR=${PWD}/build_${BUILD_TARGET}_${BUILD_TYPE}/
+
+#we care only about dist dir, i think
+[ ! -d ${DIST_DIR} ] && { echo "No build found: $BRAND $BUILD_TARGET" && exit 255; }
+
+
+
+echo "Pack [${BUILD_TYPE}] binaries for [$BUILD_TARGET] from [${DIST_DIR}] to [${OUT_DIR}]"
+
+. ${HERE}/packaging/${BUILD_TARGET}.sh
+
+PACK ${DIST_DIR} ${BUILD_DIR} ${OUT_DIR}
+
+
+
diff --git a/prod_build/packaging/deb/config b/prod_build/packaging/deb/config
new file mode 100755
index 0000000000000000000000000000000000000000..47ad739daed123b6de28f9ce0b20f4425bb0a5fb
--- /dev/null
+++ b/prod_build/packaging/deb/config
@@ -0,0 +1,71 @@
+#!/bin/bash -e
+. /usr/share/debconf/confmodule
+
+
+case "$1" in
+reconfigure|configure)
+
+   db_input critical cellframe-node/auto_online || true 
+   db_go || true 
+
+   db_input critical cellframe-node/debug_mode || true 
+   db_go || true 
+
+   db_input critical cellframe-node/server_enabled || true 
+   db_go || true 
+
+   db_input critical cellframe-node/server_addr || true 
+   db_go || true 
+
+   db_input critical cellframe-node/server_port || true 
+   db_go || true 
+
+   db_input critical cellframe-node/notify_srv_addr || true 
+   db_go || true 
+
+   db_input critical cellframe-node/notify_srv_port || true 
+   db_go || true 
+
+   db_input critical cellframe-node/subzero_enabled || true 
+   db_go || true 
+
+   db_get cellframe-node/subzero_enabled
+   if [ "$RET" = "true" ]; then
+      db_input critical cellframe-node/subzero_node_type || true 
+      db_go || true
+   fi
+
+   db_input critical cellframe-node/kelvpn_minkowski_enabled || true 
+   db_go || true 
+
+   db_get cellframe-node/kelvpn_minkowski_enabled
+   if [ "$RET" = "true" ]; then
+      db_input critical cellframe-node/kelvpn_minkowski_node_type || true 
+      db_go || true
+   fi
+
+   db_input critical cellframe-node/backbone_enabled || true 
+   db_go || true 
+
+   db_get cellframe-node/backbone_enabled
+   if [ "$RET" = "true" ]; then
+      db_input critical cellframe-node/backbone_node_type || true 
+      db_go || true
+   fi
+
+   db_input critical cellframe-node/enable_python_plugins || true 
+   db_go || true 
+
+   db_get cellframe-node/enable_python_plugins
+   if [ "$RET" = "true" ]; then
+      db_input critical cellframe-node/python_plugins_path || true 
+      db_go || true
+   fi
+;;
+*)
+   echo "config called with unknown argument \`$1'" >&2
+   exit 1
+;;
+esac
+
+
diff --git a/prod_build/packaging/deb/postinst b/prod_build/packaging/deb/postinst
new file mode 100755
index 0000000000000000000000000000000000000000..aa9f7a0cab6eb9520f6f941bf7de51860434755b
--- /dev/null
+++ b/prod_build/packaging/deb/postinst
@@ -0,0 +1,190 @@
+#!/bin/bash -e
+. /usr/share/debconf/confmodule
+
+DAP_CHAINS_NAME="cellframe"
+DAP_APP_NAME="${DAP_CHAINS_NAME}-node"
+DAP_PREFIX="/opt/${DAP_APP_NAME}"
+
+DAP_CFG_TPL="${DAP_PREFIX}/share/configs/${DAP_APP_NAME}.cfg.tpl"
+
+# Store write config to new if present smth
+DAP_CFG="${DAP_PREFIX}/etc/${DAP_APP_NAME}.cfg"
+
+[ -e "/etc/profile.d/${DAP_APP_NAME}.sh" ] || ln -sf ${DAP_PREFIX}/share/profile.d/${DAP_APP_NAME}.sh /etc/profile.d/${DAP_APP_NAME}.sh
+
+# Init node config
+if [ -e "${DAP_CFG}" ]; then
+    DAP_CFG="${DAP_PREFIX}/etc/${DAP_APP_NAME}.cfg.dpkg-new"
+else
+    DAP_CFG="${DAP_PREFIX}/etc/${DAP_APP_NAME}.cfg"
+fi
+
+cat ${DAP_CFG_TPL} > ${DAP_CFG} || true
+
+sed -i "s/{PREFIX}/\/opt\/${DAP_APP_NAME}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/debug_mode || true
+sed -i "s/{DEBUG_MODE}/${RET}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/auto_online || true
+sed -i "s/{AUTO_ONLINE}/${RET}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/server_enabled || true
+sed -i "s/{SERVER_ENABLED}/${RET}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/server_port || true
+sed -i "s/{SERVER_PORT}/${RET}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/server_addr || true
+sed -i "s/{SERVER_ADDR}/${RET}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/notify_srv_addr || true
+sed -i "s/{NOTIFY_SRV_ADDR}/${RET}/g" ${DAP_CFG}  || true
+
+db_get cellframe-node/notify_srv_port || true
+sed -i "s/{NOTIFY_SRV_PORT}/${RET}/g" ${DAP_CFG}  || true
+
+# Init subzero
+NET_NAME="subzero"
+
+db_get cellframe-node/subzero_enabled || true
+if [ "${RET}" = "true" ]; then
+    DAP_CFG_NET="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    DAP_CFG_NET_TPL="${DAP_PREFIX}/share/configs/network/${NET_NAME}.cfg.tpl"
+    DAP_NET_CFG=""
+    
+    if [ -e "$DAP_CFG_NET" ]; then
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg.dpkg-new"
+    else
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    fi
+
+    cat ${DAP_CFG_NET_TPL} > ${DAP_NET_CFG} || true
+    db_get cellframe-node/subzero_node_type || true
+    NODE_TYPE=${RET}
+    sed -i "s/{NODE_TYPE}/${NODE_TYPE}/g" ${DAP_NET_CFG}  || true
+    echo "[*] Enabled subzero"
+fi
+
+# Init mileena
+NET_NAME="mileena"
+
+db_get cellframe-node/mileena_enabled || true
+if [ "$RET" = "true" ]; then
+    DAP_CFG_NET="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    DAP_CFG_NET_TPL="${DAP_PREFIX}/share/configs/network/${NET_NAME}.cfg.tpl"
+    DAP_NET_CFG=""
+    
+    if [ -e "${DAP_CFG_NET}" ]; then
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg.dpkg-new"
+    else
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    fi
+
+    cat ${DAP_CFG_NET_TPL} > ${DAP_NET_CFG} || true
+    db_get cellframe-node/mileena_node_type || true
+    NODE_TYPE=${RET}
+    sed -i "s/{NODE_TYPE}/${NODE_TYPE}/g" ${DAP_NET_CFG}  || true
+    echo "[*] Enabled mileena"
+fi
+
+# Init Minkowski
+NET_NAME="kelvpn-minkowski"
+
+db_get cellframe-node/kelvpn_minkowski_enabled || true
+if [ "${RET}" = "true" ]; then
+    DAP_CFG_NET="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    DAP_CFG_NET_TPL="${DAP_PREFIX}/share/configs/network/${NET_NAME}.cfg.tpl"
+    DAP_NET_CFG=""
+    
+    if [ -e "$DAP_CFG_NET" ]; then
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg.dpkg-new"
+    else
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    fi
+
+    cat ${DAP_CFG_NET_TPL} > ${DAP_NET_CFG} || true
+    db_get cellframe-node/kelvpn_minkowski_node_type || true
+    NODE_TYPE=${RET}
+    sed -i "s/{NODE_TYPE}/${NODE_TYPE}/g" ${DAP_NET_CFG}  || true
+    echo "[*] Enabled kelvpn-minkowski"
+fi
+
+# Init Backbone
+NET_NAME="Backbone"
+
+db_get cellframe-node/backbone_enabled || true
+if [ "${RET}" = "true" ]; then
+    DAP_CFG_NET="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    DAP_CFG_NET_TPL="${DAP_PREFIX}/share/configs/network/${NET_NAME}.cfg.tpl"
+    DAP_NET_CFG=""
+    
+    if [ -e "${DAP_CFG_NET}" ]; then
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg.dpkg-new"
+    else
+	DAP_NET_CFG="${DAP_PREFIX}/etc/network/${NET_NAME}.cfg"
+    fi
+
+    cat ${DAP_CFG_NET_TPL} > ${DAP_NET_CFG} || true
+    db_get cellframe-node/backbone_node_type || true
+    NODE_TYPE=$RET
+    sed -i "s/{NODE_TYPE}/${NODE_TYPE}/g" ${DAP_NET_CFG}  || true
+    echo "[*] Enabled Backbone"
+fi
+
+#Set up Python plugins
+db_get cellframe-node/enable_python_plugins || true
+if [ "${RET}" = "true" ]; then
+    sed -i 's/#\[plugins\]/\[plugins\]/g' ${DAP_CFG} || true
+    sed -i 's/#py_load=.*/py_load=true/g' ${DAP_CFG} || true
+    db_get cellframe-node/python_plugins_path || true
+    sed -i "s|#py_path=.*|py_path=${RET}|g" ${DAP_CFG} || true
+    echo "[*] Enabled Python plugins"
+fi
+
+if [ $(cat /etc/passwd | grep ${DAP_APP_NAME}) ] ; then
+    usermod ${DAP_APP_NAME} -s /bin/false > /dev/null || true # Let's change the default shell just in case
+else
+    echo "[*] Add user ${DAP_APP_NAME}"
+    adduser --system --no-create-home --group --home /opt/${DAP_APP_NAME} ${DAP_APP_NAME} --shell /bin/false > /dev/null || true
+fi
+
+echo "[*] Check if /etc/systemd/system/${DAP_APP_NAME}.service file is available..."
+if [ -e /etc/systemd/system/${DAP_APP_NAME}.service ]; then
+    echo "[*] File found, restarting ${DAP_APP_NAME} to implement changes"
+    systemctl daemon-reload || true
+    systemctl start ${DAP_APP_NAME} || true
+    echo "[!] Done"
+else
+    echo "[!] Installing ${DAP_APP_NAME} as systemd service"
+    ln -sf $DAP_PREFIX/share/${DAP_APP_NAME}.service /etc/systemd/system/${DAP_APP_NAME}.service || true
+    systemctl enable ${DAP_PREFIX}/share/${DAP_APP_NAME}.service || true
+    echo "[*] Enabling logrotate"
+    ln -sf ${DAP_PREFIX}/share/logrotate/${DAP_APP_NAME} /etc/logrotate.d/${DAP_APP_NAME} || true
+
+    mkdir -p ${DAP_PREFIX}/var/{run,lib/wallet,lib/global_db,lib/plugins,log} || true
+    
+    touch ${DAP_PREFIX}/var/run/${DAP_APP_NAME}.pid || true
+    
+    for filename in $(find ${DAP_PREFIX} | grep -v bugreport); do
+        if [ -d ${filename} ]; then
+            chmod 0775 ${filename} 2>/dev/null || true
+        else
+            chmod 0664 ${filename} 2>/dev/null || true
+        fi
+    done
+
+    chmod 0666 ${DAP_CFG}
+    chmod 0666 ${DAP_CFG_TPL}
+    chmod 0775 ${DAP_PREFIX}/bin/* || true
+
+    #set python permissions    
+    find ${DAP_PREFIX}/bin/python -type d -exec chmod 755 {} +
+    chmod 774 ${DAP_PREFIX}/bin/python/bin/* || true
+    chown -R ${DAP_APP_NAME}: ${DAP_PREFIX}
+    echo "[*] Starting ${DAP_APP_NAME} service"
+    systemctl start ${DAP_APP_NAME} || true
+    echo "[!] Done"
+fi
+
+exit 0
\ No newline at end of file
diff --git a/prod_build/packaging/deb/postrm b/prod_build/packaging/deb/postrm
new file mode 100755
index 0000000000000000000000000000000000000000..a51227920729a6e763a7637a50924e3b990068c3
--- /dev/null
+++ b/prod_build/packaging/deb/postrm
@@ -0,0 +1,42 @@
+#!/bin/bash 
+
+DAP_CHAINS_NAME="cellframe"
+DAP_APP_NAME="${DAP_CHAINS_NAME}-node"
+DAP_PREFIX="/opt/${DAP_APP_NAME}"
+
+GDB_PATH=`cat ${DAP_PREFIX}/etc/${DAP_APP_NAME}.cfg | grep -oP "^dap_global_db_path=\K.*"`
+CONFFILES="${DAP_PREFIX}/etc/"
+
+
+case "$1" in
+    purge)
+    # Purge database
+    if [ -e /usr/share/debconf/confmodule ] ; then
+        . /usr/share/debconf/confmodule
+        db_purge
+    fi
+    # Remove user and group
+    echo "[*] Removing user cellframe-node"
+    userdel ${DAP_APP_NAME} > /dev/null || true
+    echo "[*] Removing group cellframe-node"
+    groupdel ${DAP_APP_NAME} > /dev/null || true
+
+    # Remove configuration file, logs and at least gdb path for now on purge
+    echo "[*] Removing configuration files for ${DAP_APP_NAME}"
+    rm -rf ${CONFFILES} || true
+    echo "[*] Removing log files for ${DAP_APP_NAME}"
+    rm -rf ${DAP_PREFIX}/var/log || true
+    echo "[*] Removing databases for ${DAP_APP_NAME}"
+    rm -rf ${GDB_PATH} || true
+    ;;
+
+    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+    ;;
+
+    *)
+        echo "postrm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+exit 0
\ No newline at end of file
diff --git a/prod_build/packaging/deb/prerm b/prod_build/packaging/deb/prerm
new file mode 100755
index 0000000000000000000000000000000000000000..b961ff4342a99fd228b18e4b50983163fc3ef8a7
--- /dev/null
+++ b/prod_build/packaging/deb/prerm
@@ -0,0 +1,29 @@
+#!/bin/bash -e
+
+case "$1" in
+	remove|purge|abort-install|abort-upgrade)
+		echo "[*] Stopping cellframe-node.service"
+		systemctl stop cellframe-node || true
+		echo "[*] Disabling cellframe-node.service"
+		systemctl disable cellframe-node || true
+		;;
+
+	disappear)
+		;;
+
+	upgrade)
+		echo "[*] Stopping cellframe-node.service"
+        systemctl stop cellframe-node || true
+		;;
+
+	failed-upgrade)
+		echo "[*] Stopping cellframe-node.service"
+        systemctl stop cellframe-node || true
+        ;;
+
+	*)
+	    echo "prerm called with unknown argument \`$1'" >&2
+		exit 1;;
+esac
+
+exit 0
diff --git a/prod_build/packaging/deb/rules b/prod_build/packaging/deb/rules
new file mode 100755
index 0000000000000000000000000000000000000000..8ebdadfdb53a9504434765cae4080c4283f54437
--- /dev/null
+++ b/prod_build/packaging/deb/rules
@@ -0,0 +1,10 @@
+#!/usr/bin/make -f
+
+override_dh_fixperms:
+    dh_fixperms -X/opt/cellframe-node
+    chmod 777 /opt/cellframe-node/bin/cellframe-node-cli
+override_dh_auto_install:
+    dh_auto_install -- prefix=/opt/cellframe-node
+%:
+#    dh $@  --with=systemd
+    dh $@
diff --git a/prod_build/packaging/deb/templates b/prod_build/packaging/deb/templates
new file mode 100755
index 0000000000000000000000000000000000000000..53d7dd3a1369481e852da47c8e5224c8c63b23ce
--- /dev/null
+++ b/prod_build/packaging/deb/templates
@@ -0,0 +1,133 @@
+Template: cellframe-node/auto_online
+Default: false
+Choices: true, false
+Type: select
+Description: Auto online
+ Bring up links automatically and go to ONLINE network state
+
+Template: cellframe-node/debug_mode
+Default: false
+Choices: true, false
+Type: select
+Description: Debug mode
+ Debug mode for logs
+
+Template: cellframe-node/server_enabled
+Default: false
+Choices: true, false
+Type: select
+Description: Accept connections
+ Accept connections 
+
+Template: cellframe-node/server_port
+Default: 8079
+Type: string
+Description: Server port
+ Server port to listen on, recommended 8079 
+
+Template: cellframe-node/server_addr
+Default: 0.0.0.0
+Type: string
+Description: Server address
+ Server address to listen on
+
+Template: cellframe-node/notify_srv_addr
+Default: 127.0.0.1
+Type: string
+Description: Notify server address
+ Notify server address to listen on
+
+Template: cellframe-node/notify_srv_port
+Default: 8080
+Type: string
+Description: Notify server port
+ Notify server port to listen on 
+
+Template: cellframe-node/subzero_enabled
+Default: true
+Choices: true, false
+Type: select
+Description: SubZero: Enable network
+ Subzero Testnet: Enable network auto load on start
+
+Template: cellframe-node/subzero_node_type
+Type: select
+Default: full
+Choices: full, light, master, archive, root
+Description: SubZero: Node role
+ Select node role:. 
+ Light - Synchronize only local wallets 
+ full - Sync all its cell
+ master - Allow to store values in chains and take comission, sync all shards that will need to be synced
+ archive - Sync all the network
+ root - Special predefined root nodes, usually produces zerochain and acts like archive as well
+
+Template: cellframe-node/mileena_enabled
+Default: true
+Choices: true, false
+Type: select
+Description: Mileena: Enable network
+ Mileena Testnet: Enable network auto load on start
+
+Template: cellframe-node/mileena_node_type
+Type: select
+Default: full
+Choices: full, light, master, archive, root
+Description: Mileena: Node role
+ Select node role:. 
+ Light - Synchronize only local wallets 
+ full - Sync all its cell
+ master - Allow to store values in chains and take comission, sync all shards that will need to be synced
+ archive - Sync all the network
+ root - Special predefined root nodes, usually produces zerochain and acts like archive as well
+
+Template: cellframe-node/kelvpn_minkowski_enabled
+Default: true
+Choices: true, false
+Type: select
+Description: Kelvpn Minkowski: Enable network
+ Minkowski Testnet: Enable network auto load on start
+
+Template: cellframe-node/kelvpn_minkowski_node_type
+Type: select
+Default: full
+Choices: full, light, master, archive, root
+Description: Kelvpn Minkowski: Node role
+ Select node role:. 
+ Light - Synchronize only local wallets 
+ full - Sync all its cell
+ master - Allow to store values in chains and take comission, sync all shards that will need to be synced
+ archive - Sync all the network
+ root - Special predefined root nodes, usually produces zerochain and acts like archive as well 
+
+Template: cellframe-node/backbone_enabled
+Default: true
+Choices: true, false
+Type: select
+Description: Backbone: Enable network
+ Backbone Mainnet: Enable network auto load on start
+
+Template: cellframe-node/backbone_node_type
+Type: select
+Default: full
+Choices: full, light, master, archive, root
+Description: Backbone: Node role
+ Select node role:. 
+ Light - Synchronize only local wallets 
+ full - Sync all its cell
+ master - Allow to store values in chains and take comission, sync all shards that will need to be synced
+ archive - Sync all the network
+ root - Special predefined root nodes, usually produces zerochain and acts like archive as well
+
+Template: cellframe-node/enable_python_plugins
+Default: false
+Choices: true, false
+Type: select
+Description: Python plugins: Enable Python plugins
+ Python plugins: Enable Python plugins
+
+Template: cellframe-node/python_plugins_path
+Default: /opt/cellframe-node/var/lib/plugins
+Type: string
+Description: Python plugins path
+ Path for Python plugins
\ No newline at end of file
diff --git a/prod_build/packaging/linux.sh b/prod_build/packaging/linux.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8a6541235b8870d68857b95d627e5aa0bdd39aea
--- /dev/null
+++ b/prod_build/packaging/linux.sh
@@ -0,0 +1,50 @@
+#!/bin/bash -e
+
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+
+FILL_VERSION()
+{
+    source "${HERE}/../version.mk"
+
+    VERSION_UPDATE="s|VERSION_MAJOR|${VERSION_MAJOR}|g"
+    BUILD_UPDATE="s|VERSION_MINOR|${VERSION_MINOR}|g"
+    MAJOR_UPDATE="s|VERSION_PATCH|${VERSION_PATCH}|g"
+
+    for TEMPLATE in "$@"; do
+        sed \
+            -e "${VERSION_UPDATE}" \
+            -e "${BUILD_UPDATE}" \
+            -e "${MAJOR_UPDATE}" \
+            -i "${TEMPLATE}"
+    done
+}
+
+PACK() 
+{
+    
+    DIST_DIR=$1
+    BUILD_DIR=$2
+    OUT_DIR=$3
+
+    cd $BUILD_DIR
+    cpack ./
+    cp *.deb ${OUT_DIR}
+}
diff --git a/prod_build/packaging/osx.sh b/prod_build/packaging/osx.sh
new file mode 100644
index 0000000000000000000000000000000000000000..3ef622c1a2b8fb21be4ca375367e15272cf2139a
--- /dev/null
+++ b/prod_build/packaging/osx.sh
@@ -0,0 +1,152 @@
+#!/bin/bash -e
+
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+
+PKG_SIGN_POSSIBLE=1
+
+if [ -z "$OSX_PKEY_INSTALLER" ]
+then
+	echo "No OSX_PKEY_INSTALLER provided. PKG will NOT be signed"
+	PKG_SIGN_POSSIBLE=0
+fi
+
+if [ -z "$OSX_PKEY_APPLICATION" ]
+then
+	echo "No OSX_PKEY_APPLICATION provided. PKG will NOT be signed"
+	PKG_SIGN_POSSIBLE=0
+fi
+
+if [ -z "$OSX_PKEY_INSTALLER_PASS" ]
+then
+	echo "No OSX_PKEY_INSTALLER_PASS provided. PKG will NOT be signed"
+	PKG_SIGN_POSSIBLE=0
+fi
+
+if [ -z "$OSX_PKEY_APPLICATION_PASS" ]
+then
+	echo "No OSX_PKEY_APPLICATION_PASS provided. PKG will NOT be signed"
+	PKG_SIGN_POSSIBLE=0
+fi
+
+if [ -z "$OSX_APPSTORE_CONNECT_KEY" ]
+then
+	echo "No OSX_APPSTORE_CONNECT_KEY provided. PKG will NOT be signed"
+	PKG_SIGN_POSSIBLE=0
+fi
+
+PACK() 
+{
+    DIST_DIR=$1
+    BUILD_DIR=$2
+    OUT_DIR=$3
+
+	BRAND=CellframeNode
+
+    #USED FOR PREPARATION OF UNIFIED BUNDLE
+    #all binaries and some structure files are threre
+    PACKAGE_DIR=${DIST_DIR}/osxpackaging
+
+    #USED FOR PROCESSING OF PREPARED BUNDLE: BOM CREATION, ETC
+    OSX_PKG_DIR=${DIST_DIR}/pkg
+
+	BRAND_OSX_BUNDLE_DIR=${PACKAGE_DIR}/${BRAND}.app
+
+    #prepare correct packaging structure
+    mkdir -p ${PACKAGE_DIR}
+    mkdir -p ${OSX_PKG_DIR}
+
+    echo "Creating unified package structure in [$BRAND_OSX_BUNDLE_DIR]"
+
+    #copy base application bundle
+    #path to it in BRAND_OSX_BUNDLE_DIR
+    cp -r ${DIST_DIR}/Users/$(whoami)/Applications/Cellframe.app ${PACKAGE_DIR}/CellframeNode.app
+
+    #copy pkginstall
+	cp  ${HERE}/../../os/macos/PKGINSTALL/* ${PACKAGE_DIR}
+
+	echo "Do packaging magic in [$PACKAGE_DIR]"
+	cd $wd
+	
+	#get version info
+	source "${HERE}/../../version.mk"
+    PACKAGE_NAME="cellframe-node_${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}_amd64.pkg"
+	PACKAGE_NAME_SIGNED="cellframe-node_${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}_amd64-signed.pkg"
+    echo "Building package [$PACKAGE_NAME]"
+
+	#prepare
+	PAYLOAD_BUILD=${PACKAGE_DIR}/payload_build
+	SCRIPTS_BUILD=${PACKAGE_DIR}/scripts_build
+
+	mkdir -p ${PAYLOAD_BUILD}
+	mkdir -p ${SCRIPTS_BUILD}
+
+	cp ${PACKAGE_DIR}/${BRAND}.plist ${PAYLOAD_BUILD}
+	cp -r ${BRAND_OSX_BUNDLE_DIR} ${PAYLOAD_BUILD}
+
+	
+	cp ${PACKAGE_DIR}/preinstall ${SCRIPTS_BUILD}
+	cp ${PACKAGE_DIR}/postinstall ${SCRIPTS_BUILD}
+
+	#create .pkg struture to further xar coommand
+
+	#code-sign binaries
+	if [ "$PKG_SIGN_POSSIBLE" -eq "1" ]; then
+		echo "Code-signig binaries"
+		#add runtime flag to bypass notarization warnings about hardened runtime.
+		rcodesign sign --code-signature-flags runtime --p12-file ${OSX_PKEY_APPLICATION} --p12-password ${OSX_PKEY_APPLICATION_PASS} ${PAYLOAD_BUILD}/${BRAND}.app
+	fi
+
+	# create bom file
+	mkbom -u 0 -g 80 ${PAYLOAD_BUILD} ${OSX_PKG_DIR}/Bom
+
+	# create Payload
+	(cd ${PAYLOAD_BUILD} && find . | cpio -o --format odc --owner 0:80 | gzip -c) > ${OSX_PKG_DIR}/Payload
+	# create Scripts
+	(cd ${SCRIPTS_BUILD} && find . | cpio -o --format odc --owner 0:80 | gzip -c) > ${OSX_PKG_DIR}/Scripts
+
+	#update PkgInfo
+	cp ${PACKAGE_DIR}/PackageInfo ${OSX_PKG_DIR}
+
+	numberOfFiles=$(find ${PAYLOAD_BUILD} | wc -l)
+	installKBytes=$(du -k -s ${PAYLOAD_BUILD} | cut -d"$(echo -e '\t')" -f1)
+	sed -i "s/numberOfFiles=\"[0-9]\+\"/numberOfFiles=\"$numberOfFiles\"/g" ${OSX_PKG_DIR}/PackageInfo
+	sed -i "s/installKBytes=\"[0-9]\+\"/installKBytes=\"$installKBytes\"/" ${OSX_PKG_DIR}/PackageInfo
+
+	(cd $OSX_PKG_DIR && xar --compression none -cf ../../${PACKAGE_NAME} *)
+	
+	#check if we can sign pkg
+	#for certificate preparation see this guide: https://users.wfu.edu/cottrell/productsign/productsign_linux.html
+	#for other things see rcodesing help
+
+	if [ "$PKG_SIGN_POSSIBLE" -eq "1" ]; then
+		echo "Signig $PACKAGE_NAME to $PACKAGE_NAME_SIGNED"
+
+		cd ${OUT_DIR}
+		
+		rcodesign sign --p12-file ${OSX_PKEY_INSTALLER} --p12-password ${OSX_PKEY_INSTALLER_PASS} ${PACKAGE_NAME} ${PACKAGE_NAME_SIGNED}
+		
+		echo "Notarizing package"
+		rcodesign notary-submit --api-key-path ${OSX_APPSTORE_CONNECT_KEY} ${PACKAGE_NAME_SIGNED} --staple
+		rm ${PACKAGE_NAME}
+	fi
+}
+
+
diff --git a/prod_build/targets/android.sh b/prod_build/targets/android.sh
new file mode 100644
index 0000000000000000000000000000000000000000..66d52f2ee5d15e9744b48a99e974de4706f2e32e
--- /dev/null
+++ b/prod_build/targets/android.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -e
+
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+if [ -z "$ANDROID_CMAKE_TOOLCHAIN" ]
+then
+      echo "ANDROID_CMAKE_TOOLCHAIN not defined!"
+      exit 1
+fi
+
+CMAKE=(cmake -DCMAKE_TOOLCHAIN_FILE=${ANDROID_CMAKE_TOOLCHAIN})
+MAKE=(make)
+
+echo "Android target"
+echo "CMAKE=${CMAKE[@]}"
+echo "MAKE=${MAKE[@]}"
diff --git a/prod_build/targets/linux.sh b/prod_build/targets/linux.sh
new file mode 100644
index 0000000000000000000000000000000000000000..aa1560b2c74a38180a7cd029c51035ada35d20f7
--- /dev/null
+++ b/prod_build/targets/linux.sh
@@ -0,0 +1,27 @@
+#!/bin/bash -e
+
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+CMAKE=(cmake)
+MAKE=(make)
+
+echo "Linux target"
+echo "CMAKE=${CMAKE[@]}"
+echo "MAKE=${MAKE[@]}"
diff --git a/prod_build/targets/osx.sh b/prod_build/targets/osx.sh
new file mode 100644
index 0000000000000000000000000000000000000000..67f76e6a7956c63a6f9c3f2b3c58b11bf87807b7
--- /dev/null
+++ b/prod_build/targets/osx.sh
@@ -0,0 +1,87 @@
+#!/bin/bash -e
+#OSX BUILD 
+#HAVE TO PROVIDE OSXCROSS_QT_ROOT variable
+#HAVE TO PROVIDE OSXCROSS_QT_VERSION variable
+
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+UNAME_OUT="$(uname -s)"
+case "${UNAME_OUT}" in
+    Linux*)     MACHINE=Linux;;
+    Darwin*)    MACHINE=Mac;;
+    CYGWIN*)    MACHINE=Cygwin;;
+    MINGW*)     MACHINE=MinGw;;
+    MSYS_NT*)   MACHINE=Git;;
+    *)          MACHINE="UNKNOWN:${UNAME_OUT}"
+esac
+
+if [ "$MACHINE" != "Mac" ]
+then
+  echo "Host is $MACHINE, use osx-cross build target"
+  if [ -z "$OSXCROSS_QT_ROOT" ]
+  then
+        echo "Please, export OSXCROSS_QT_ROOT variable, pointing to Qt-builds locations for osxcross environment"
+        exit 255
+  fi
+
+
+  if [ -z "$OSXCROSS_QT_VERSION" ]
+  then
+        echo "Please, export OSXCROSS_QT_VERSION variable, scpecifying Qt-version in OSXCROSS_QT_ROOT directory."
+        exit 255
+  fi
+
+  echo "Using QT ${OSXCROSS_QT_VERSION} from ${OSXCROSS_QT_ROOT}/${OSXCROSS_QT_VERSION}"
+
+  [ ! -d ${OSXCROSS_QT_ROOT}/${OSXCROSS_QT_VERSION} ] && { echo "No QT ${OSXCROSS_QT_VERSION} found in ${OSXCROSS_QT_ROOT}" && exit 255; }
+
+  $(${OSXCROSS_ROOT}/bin/osxcross-conf)
+
+
+  export OSXCROSS_HOST=x86_64-apple-darwin20.4
+  CMAKE=(cmake -DCMAKE_TOOLCHAIN_FILE=${OSXCROSS_ROOT}/toolchain.cmake)
+
+  ##everything else can be done by default make
+  MAKE=(make)
+
+  
+else
+    echo "Host is $MACHINE, use native build toolchain"
+
+    if [ -f "/Users/$USER/Qt/Tools/CMake/CMake.app/Contents/bin/cmake" ] 
+    then
+      CMAKE=(/Users/$USER/Qt/Tools/CMake/CMake.app/Contents/bin/cmake )
+      echo "Found QT cmake at $CMAKE, using it preferable"
+    else
+      if [ -f "/opt/homebrew/bin/cmake" ] 
+      then
+        CMAKE=(/opt/homebrew/bin/cmake)
+        echo "Found homebrew cmake at $CMAKE, using it"
+      else
+        echo "Not found cmake at default qt location, asuming it is in PATH"
+        CMAKE=(cmake)
+      fi
+    fi
+
+    ##everything else can be done by default make
+    MAKE=(make)
+fi
+echo "CMAKE=${CMAKE[@]}"
+echo "MAKE=${MAKE[@]}"
diff --git a/prod_build/targets/windows.sh b/prod_build/targets/windows.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d5e5c1aab195473d4313d2a683baa6b73c2529ba
--- /dev/null
+++ b/prod_build/targets/windows.sh
@@ -0,0 +1,56 @@
+
+#!/bin/bash -e
+#WINDWOS BUILD IS SUPPORTED BY MXE
+#HAVE TO PROVIDE MXE ROOT DIRECTORY
+set -e
+
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+
+if [ -z "$MSYSTEM_PREFIX" ] 
+then
+      echo "Not MSYS2 env, try MXE"
+      if [ -z "$MXE_ROOT" ]
+      then
+            echo "Please, export MXE_ROOT variable, pointing to MXE environment root (we will use qt, make shure it was built)"
+            echo "To build mxe, go to https://github.com/mxe/mxe, clone it, and do \"make qt5\" within it. Install dependencies if it says so." 
+            exit 255
+      else
+            #cmake command
+            #mxe install prefix if configured by mxe, need to change it
+            CMAKE=(${MXE_ROOT}/usr/bin/x86_64-w64-mingw32.static-cmake ) 
+            export PATH=${MXE_ROOT}/usr/bin:$PATH
+            #everything else can be done by default make
+            MAKE=(make)
+
+            echo "Windows target"
+            echo "CMAKE=${CMAKE[@]}"
+            echo "MAKE=${MAKE[@]}"
+      fi
+else
+      #cmake command
+      #mxe install prefix if configured by mxe, need to change it
+      CMAKE=(cmake -G "MSYS Makefiles") 
+      MAKE=(make)
+
+      echo "Windows target"
+      echo "CMAKE=${CMAKE[@]}"
+      echo "MAKE=${MAKE[@]}"
+fi
+
diff --git a/prod_build/validate.sh b/prod_build/validate.sh
new file mode 100644
index 0000000000000000000000000000000000000000..b5221d424f6931955c95dae29aee916955984324
--- /dev/null
+++ b/prod_build/validate.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+set -e
+
+SOURCE=${BASH_SOURCE[0]}
+while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET=$(readlink "$SOURCE")
+  if [[ $TARGET == /* ]]; then
+    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
+    SOURCE=$TARGET
+  else
+    DIR=$( dirname "$SOURCE" )
+    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
+    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+echo "SOURCE is '$SOURCE'"
+RDIR=$( dirname "$SOURCE" )
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+HERE="$DIR"
+
+
+
+containsElement () {
+  local e match="$1"
+  shift
+  for e; do [[ "$e" == "$match" ]] && return 0; done
+  return 1
+}
+
+
+TARGETS=(linux windows android osx)
+BUILD_TYPES=(release debug rwd)
+
+VALIDATE_TARGET()
+{
+    containsElement "$BUILD_TARGET" "${TARGETS[@]}"  || {
+        echo "Such target not implemented [$BUILD_TARGET]"
+        echo "Available targets are [${TARGETS[@]}]"
+        exit 255
+    }
+}
+
+VALIDATE_BUILD_TYPE()
+{
+    containsElement "$BUILD_TYPE" "${BUILD_TYPES[@]}"  || {
+        echo "Unknown build typed [$BUILD_TYPE]"
+        echo "Available types are [${BUILD_TYPES[@]}]"
+        exit 255
+    }
+}
+