diff --git a/cellframe-sdk b/cellframe-sdk
index 8477d1c289c036a9c2cc41471285a19d244e5e80..17abbf5f2c5c85e61847643983bde90c7486ee4f 160000
--- a/cellframe-sdk
+++ b/cellframe-sdk
@@ -1 +1 @@
-Subproject commit 8477d1c289c036a9c2cc41471285a19d244e5e80
+Subproject commit 17abbf5f2c5c85e61847643983bde90c7486ee4f
diff --git a/dists/interfaces/CellFrame/Chain.pyi b/dists/interfaces/CellFrame/Chain.pyi
index 8e319a894cbdf8edba963d4a9923cac9fdd69e5f..7baf6380c56efd15e9bd308b328250c6769dd548 100644
--- a/dists/interfaces/CellFrame/Chain.pyi
+++ b/dists/interfaces/CellFrame/Chain.pyi
@@ -54,6 +54,10 @@ class Chain(Protocol):
     def addAtomNotify(*args):
         pass
 
+    @staticmethod
+    def addAtomConfirmedNotify(*args):
+        pass
+
     @staticmethod
     def atomFindByHash(*args):
         pass
diff --git a/dists/python-modules/pycfhelpers b/dists/python-modules/pycfhelpers
index 45b607694ee0786dd1edc7fb605695701f4866c7..b70bc241c0d963f04ae93c7219ab2a2111b091b9 160000
--- a/dists/python-modules/pycfhelpers
+++ b/dists/python-modules/pycfhelpers
@@ -1 +1 @@
-Subproject commit 45b607694ee0786dd1edc7fb605695701f4866c7
+Subproject commit b70bc241c0d963f04ae93c7219ab2a2111b091b9
diff --git a/modules/cellframe-sdk/chain/include/libdap-chain-python.h b/modules/cellframe-sdk/chain/include/libdap-chain-python.h
index 62989076da9f4ccd955196b429514ce6f0ba4c0e..2b99316b4d99104c2a582154b3f38fc5a801f56f 100644
--- a/modules/cellframe-sdk/chain/include/libdap-chain-python.h
+++ b/modules/cellframe-sdk/chain/include/libdap-chain-python.h
@@ -45,6 +45,7 @@ PyObject *dap_chain_python_atom_iter_get_next(PyObject *self, PyObject *args);
 PyObject *dap_chain_python_atom_iter_get_dag(PyObject *self, PyObject *args);
 PyObject *dap_chain_python_add_mempool_notify_callback(PyObject *self, PyObject *args);
 PyObject *dap_chain_net_add_atom_notify_callback(PyObject *self, PyObject *args);
+PyObject *dap_chain_atom_confirmed_notify_add_py(PyObject *self, PyObject *args);
 PyObject *dap_chain_python_atom_find_by_hash(PyObject *self, PyObject* args);
 
 PyObject *dap_chain_python_get_atom_count(PyObject *self, PyObject *args);
diff --git a/modules/cellframe-sdk/chain/src/libdap-chain-python.c b/modules/cellframe-sdk/chain/src/libdap-chain-python.c
index 0f9a463a87924226d040d537891bde923a54b183..a5b065c2f63c739b7f2ef6bad038daa7275d346d 100644
--- a/modules/cellframe-sdk/chain/src/libdap-chain-python.c
+++ b/modules/cellframe-sdk/chain/src/libdap-chain-python.c
@@ -34,6 +34,7 @@ static PyMethodDef DapChainMethods[] = {
         {"getCSName", (PyCFunction)dap_chain_python_get_cs_name, METH_NOARGS, ""},
         {"getNet", (PyCFunction) dap_chain_python_get_net, METH_NOARGS, ""},
         {"configGetItem", (PyCFunction)dap_chain_python_get_config_item, METH_VARARGS, ""},
+        {"addAtomConfirmedNotify", (PyCFunction)dap_chain_atom_confirmed_notify_add_py, METH_VARARGS, "Add a callback for confirmed atoms"},
         {}
 };
 
@@ -316,6 +317,43 @@ static void _wrapping_dap_chain_atom_notify_handler(void * a_arg, dap_chain_t *a
     PyGILState_Release(state);
 }
 
+static void _wrapping_dap_chain_atom_confirmed_notify_handler(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, dap_hash_fast_t *a_hash, void *a_atom, size_t a_atom_size){
+    if (!a_arg) {
+        return;
+    }
+    _wrapping_chain_mempool_notify_callback_t *l_callback = (_wrapping_chain_mempool_notify_callback_t *)a_arg;
+
+    PyGILState_STATE state = PyGILState_Ensure();
+
+    dap_chain_atom_ptr_t l_atom = (dap_chain_atom_ptr_t)a_atom;
+    PyChainAtomObject *l_atom_obj = NULL;
+    if (l_atom) {
+        l_atom_obj = PyObject_New(PyChainAtomObject, &DapChainAtomPtrObjectType);
+        l_atom_obj->atom = l_atom;
+        l_atom_obj->atom_size = a_atom_size;
+        PyObject *l_args = Py_BuildValue("OO", l_atom_obj, l_callback->arg);
+        log_it(L_DEBUG, "Call atom confirmed notifier for chain %s with atom size %zd", a_chain->name, a_atom_size);
+        PyObject *result = PyObject_CallObject(l_callback->func, l_args);
+        if (!result) {
+            python_error_in_log_it(LOG_TAG);
+        }
+        Py_XDECREF(result);
+        Py_DECREF(l_args);
+        Py_DECREF(l_atom_obj);
+    } else {
+        PyObject *l_args = Py_BuildValue("OO", Py_None, l_callback->arg);
+        PyObject *result = PyObject_CallObject(l_callback->func, l_args);
+        if (!result) {
+            python_error_in_log_it(LOG_TAG);
+        }
+        Py_XDECREF(result);
+        Py_DECREF(l_args);
+    }
+
+    PyGILState_Release(state);
+}
+
+
 /**
  * @brief dap_chain_python_add_mempool_notify_callback
  * @param self
@@ -380,6 +418,42 @@ PyObject *dap_chain_net_add_atom_notify_callback(PyObject *self, PyObject *args)
     Py_RETURN_NONE;
 }
 
+/**
+ * @brief dap_chain_atom_confirmed_notify_add_py
+ * @param self
+ * @param args
+ * @return
+ */
+PyObject *dap_chain_atom_confirmed_notify_add_py(PyObject *self, PyObject *args)
+{
+    dap_chain_t *l_chain = ((PyDapChainObject *)self)->chain_t;
+    PyObject *obj_func;
+    PyObject *obj_arg;
+    int conf_cnt = 0;
+    if (!PyArg_ParseTuple(args, "OOi", &obj_func, &obj_arg, &conf_cnt)) {
+        PyErr_SetString(PyExc_AttributeError, "Arguments must be a callable and an argument");
+        return NULL;
+    }
+    if (!PyCallable_Check(obj_func)) {
+        PyErr_SetString(PyExc_AttributeError, "First argument must be a callable function");
+        return NULL;
+    }
+    _wrapping_chain_mempool_notify_callback_t *l_callback = DAP_NEW_Z(_wrapping_chain_mempool_notify_callback_t);
+    if (!l_callback) {
+        log_it(L_CRITICAL, "Memory allocation error");
+        return NULL;
+    }
+    l_callback->func = obj_func;
+    l_callback->arg = obj_arg;
+    Py_INCREF(obj_func);
+    Py_INCREF(obj_arg);
+    log_it(L_DEBUG, "Added confirmed atom notify in %s:%s for %d confirmations", l_chain->net_name, l_chain->name, conf_cnt);
+
+    dap_chain_atom_confirmed_notify_add(l_chain, _wrapping_dap_chain_atom_confirmed_notify_handler, l_callback, conf_cnt);
+    Py_RETURN_NONE;
+}
+
+
 /**
  * @brief dap_chain_python_atom_find_by_hash
  * @param self