diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000000000000000000000000000000000000..393611e641d78fb1da1df5efc68ce7fdce5cc8b3
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,3 @@
+[alias]
+bd = "make android-dev32"
+br = "make"
diff --git a/Cargo.lock b/Cargo.lock
index 93595d1cd24bfec19adf22da9c796b9ef5675286..2c6ad0e9d86f50b912ee93e6cd2c9b6a1a7a8171 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -59,6 +59,15 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
+[[package]]
+name = "async-oneshot"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f4770cbbff928c30a991de67fb3976f44d8e3e202f8c79ef91b47006e04904"
+dependencies = [
+ "futures-micro",
+]
+
 [[package]]
 name = "atty"
 version = "0.2.14"
@@ -245,6 +254,8 @@ dependencies = [
  "cbindgen",
  "dart-bindgen",
  "dup-crypto",
+ "fast-threadpool",
+ "once_cell",
  "thiserror",
 ]
 
@@ -270,6 +281,32 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "fast-threadpool"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccb66774e02743b4be61c19e09bf59de9058e9a7b4096040689003e7a901a3d"
+dependencies = [
+ "async-oneshot",
+ "flume",
+ "num_cpus",
+]
+
+[[package]]
+name = "flume"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0362ef9c4c1fa854ff95b4cb78045a86e810d804dc04937961988b45427104a9"
+dependencies = [
+ "spinning_top",
+]
+
+[[package]]
+name = "futures-micro"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61e9325be55c5581082cd110294fa988c1f920bc573ec370ef201e33c469a95a"
+
 [[package]]
 name = "generic-array"
 version = "0.14.4"
@@ -344,6 +381,15 @@ version = "0.2.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
 
+[[package]]
+name = "lock_api"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
+dependencies = [
+ "scopeguard",
+]
+
 [[package]]
 name = "log"
 version = "0.4.11"
@@ -353,6 +399,16 @@ dependencies = [
  "cfg-if 0.1.10",
 ]
 
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.5.2"
@@ -466,6 +522,12 @@ version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
 
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
 [[package]]
 name = "serde"
 version = "1.0.118"
@@ -503,6 +565,15 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
+[[package]]
+name = "spinning_top"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e529d73e80d64b5f2631f9035113347c578a1c9c7774b83a2b880788459ab36"
+dependencies = [
+ "lock_api",
+]
+
 [[package]]
 name = "strsim"
 version = "0.8.0"
diff --git a/native/dubp_rs/Cargo.toml b/native/dubp_rs/Cargo.toml
index feeb05b8b5252ee1601a36e44610ad0e64c85681..58d56c9965f15e322c2c35dce7e4d43f7fdec7ae 100644
--- a/native/dubp_rs/Cargo.toml
+++ b/native/dubp_rs/Cargo.toml
@@ -11,6 +11,8 @@ crate-type = ["rlib"]
 [dependencies]
 allo-isolate = "0.1.6"
 dup-crypto = { version = "0.36.0", features = ["dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] }
+fast-threadpool = { version = "0.3.0", default-features = false }
+once_cell = { version = "1.3.1", default-features = false, features = ["std"] }
 thiserror = "1.0.23"
 
 [build-dependencies]
diff --git a/native/dubp_rs/src/async.rs b/native/dubp_rs/src/async.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b7ce764f7ddade63d121065f6b91b714f4626347
--- /dev/null
+++ b/native/dubp_rs/src/async.rs
@@ -0,0 +1,42 @@
+//  Copyright (C) 2020  Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use crate::*;
+
+static THREAD_POOL: Lazy<ThreadPoolSyncHandler<()>> = Lazy::new(|| {
+    ThreadPool::start(ThreadPoolConfig::low().queue_size(Some(16)), ()).into_sync_handler()
+});
+
+pub(crate) fn exec_async<F, F2, P, R>(port: i64, parse_params: F, async_job: F2)
+where
+    P: 'static + Send + Sync,
+    F: FnOnce() -> Result<P, DubpError>,
+    F2: 'static + Send + Sync + FnOnce(P) -> R,
+    DartRes: From<R>,
+{
+    match parse_params() {
+        Ok(parsed_params) => {
+            if THREAD_POOL
+                .launch(move |_| Isolate::new(port).post(DartRes::from(async_job(parsed_params))))
+                .is_err()
+            {
+                Isolate::new(port).post(DartRes::err("thread pool panicked"));
+            }
+        }
+        Err(e) => {
+            Isolate::new(port).post(DartRes::err(e));
+        }
+    }
+}
diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs
index 7d0756529c534b4f5b160afb65b8520660ec0ebc..6e9932c7be4eec0e5a6ed7067c80f5f08b74d7ef 100644
--- a/native/dubp_rs/src/dewif.rs
+++ b/native/dubp_rs/src/dewif.rs
@@ -35,16 +35,11 @@ pub(super) fn gen_pin10() -> Result<String, DubpError> {
 }
 
 pub(super) fn change_pin(
-    currency: *const raw::c_char,
-    dewif: *const raw::c_char,
-    old_pin: *const raw::c_char,
-    new_pin: *const raw::c_char,
+    currency: &str,
+    dewif: &str,
+    old_pin: &str,
+    new_pin: &str,
 ) -> Result<String, DubpError> {
-    let currency = char_ptr_to_str(currency)?;
-    let dewif = char_ptr_to_str(dewif)?;
-    let old_pin = char_ptr_to_str(old_pin)?;
-    let new_pin = char_ptr_to_str(new_pin)?;
-
     let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
@@ -62,15 +57,11 @@ pub(super) fn change_pin(
 }
 
 pub(super) fn gen_dewif(
-    currency: *const raw::c_char,
+    currency: &str,
     language: u32,
-    mnemonic: *const raw::c_char,
-    pin: *const raw::c_char,
+    mnemonic: &str,
+    pin: &str,
 ) -> Result<String, DubpError> {
-    let currency = char_ptr_to_str(currency)?;
-    let mnemonic = char_ptr_to_str(mnemonic)?;
-    let pin = char_ptr_to_str(pin)?;
-
     let currency = parse_currency(currency)?;
     let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
         .map_err(|_| DubpError::WrongLanguage)?;
@@ -81,15 +72,7 @@ pub(super) fn gen_dewif(
     ))
 }
 
-pub(super) fn get_pubkey(
-    currency: *const raw::c_char,
-    dewif: *const raw::c_char,
-    pin: *const raw::c_char,
-) -> Result<String, DubpError> {
-    let currency = char_ptr_to_str(currency)?;
-    let dewif = char_ptr_to_str(dewif)?;
-    let pin = char_ptr_to_str(pin)?;
-
+pub(super) fn get_pubkey(currency: &str, dewif: &str, pin: &str) -> Result<String, DubpError> {
     let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
@@ -104,17 +87,7 @@ pub(super) fn get_pubkey(
     }
 }
 
-pub(super) fn sign(
-    currency: *const raw::c_char,
-    dewif: *const raw::c_char,
-    pin: *const raw::c_char,
-    msg: *const raw::c_char,
-) -> Result<String, DubpError> {
-    let currency = char_ptr_to_str(currency)?;
-    let dewif = char_ptr_to_str(dewif)?;
-    let pin = char_ptr_to_str(pin)?;
-    let msg = char_ptr_to_str(msg)?;
-
+pub(super) fn sign(currency: &str, dewif: &str, pin: &str, msg: &str) -> Result<String, DubpError> {
     let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
@@ -130,22 +103,11 @@ pub(super) fn sign(
 }
 
 pub(super) fn sign_several(
-    currency: *const raw::c_char,
-    dewif: *const raw::c_char,
-    pin: *const raw::c_char,
-    msgs_len: usize,
-    msgs: *const *const raw::c_char,
+    currency: &str,
+    dewif: &str,
+    pin: &str,
+    msgs: &[&str],
 ) -> Result<Vec<String>, DubpError> {
-    let currency = char_ptr_to_str(currency)?;
-    let dewif = char_ptr_to_str(dewif)?;
-    let pin = char_ptr_to_str(pin)?;
-
-    let msgs_slice: &[*const raw::c_char] = unsafe { std::slice::from_raw_parts(msgs, msgs_len) };
-    let mut msgs = Vec::with_capacity(msgs_len);
-    for ptr_c_char in msgs_slice {
-        msgs.push(char_ptr_to_str(*ptr_c_char)?);
-    }
-
     let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
diff --git a/native/dubp_rs/src/error.rs b/native/dubp_rs/src/error.rs
new file mode 100644
index 0000000000000000000000000000000000000000..63bd5ec91b8e4e3043bf93a3a5037815ac4bde49
--- /dev/null
+++ b/native/dubp_rs/src/error.rs
@@ -0,0 +1,77 @@
+//  Copyright (C) 2020  Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use crate::*;
+
+/// Dubp error
+#[derive(Debug, Error)]
+pub(crate) enum DubpError {
+    #[error("{0}")]
+    DewifReadError(DewifReadError),
+    #[error("I/O error: {0}")]
+    IoErr(io::Error),
+    #[error("A given parameter is null")]
+    NullParamErr,
+    #[error("fail to generate random bytes")]
+    RandErr,
+    #[error("Unknown currency name")]
+    UnknownCurrencyName,
+    #[error("Unknown language")]
+    UnknownLanguage,
+    #[error("{0}")]
+    Utf8Error(std::str::Utf8Error),
+    #[error("Wrong language")]
+    WrongLanguage,
+}
+
+impl From<io::Error> for DubpError {
+    fn from(e: io::Error) -> Self {
+        Self::IoErr(e)
+    }
+}
+
+pub(crate) struct DartRes(allo_isolate::ffi::DartCObject);
+impl DartRes {
+    pub(crate) fn err<E: ToString>(e: E) -> allo_isolate::ffi::DartCObject {
+        vec![format!("DUBP_RS_ERROR: {}", e.to_string())].into_dart()
+    }
+}
+impl IntoDart for DartRes {
+    fn into_dart(self) -> allo_isolate::ffi::DartCObject {
+        self.0.into_dart()
+    }
+}
+impl<E> From<Result<String, E>> for DartRes
+where
+    E: ToString,
+{
+    fn from(res: Result<String, E>) -> Self {
+        match res {
+            Ok(string) => Self(string.into_dart()),
+            Err(e) => Self(format!("DUBP_RS_ERROR: {}", e.to_string()).into_dart()),
+        }
+    }
+}
+impl<E> From<Result<Vec<String>, E>> for DartRes
+where
+    E: ToString,
+{
+    fn from(res: Result<Vec<String>, E>) -> Self {
+        match res {
+            Ok(vec_string) => Self(vec_string.into_dart()),
+            Err(e) => Self(vec![format!("DUBP_RS_ERROR: {}", e.to_string())].into_dart()),
+        }
+    }
+}
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 8d2f03abd4e355dbbd6ad765539796d0cfceea39..2f29e58282e5695239197530e0916c0509569130 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -15,9 +15,13 @@
 
 #![allow(clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref)]
 
+mod r#async;
 mod dewif;
+mod error;
 mod mnemonic;
 
+use crate::error::{DartRes, DubpError};
+use crate::r#async::exec_async;
 use allo_isolate::{IntoDart, Isolate};
 use dup_crypto::{
     bases::b58::ToBase58,
@@ -28,70 +32,38 @@ use dup_crypto::{
     },
     mnemonic::{Language, Mnemonic, MnemonicType},
 };
+use fast_threadpool::{ThreadPool, ThreadPoolConfig, ThreadPoolSyncHandler};
+use once_cell::sync::Lazy;
 use std::{ffi::CStr, io, os::raw};
 use thiserror::Error;
 
-/// Dubp error
-#[derive(Debug, Error)]
-pub enum DubpError {
-    #[error("{0}")]
-    DewifReadError(DewifReadError),
-    #[error("I/O error: {0}")]
-    IoErr(io::Error),
-    #[error("A given parameter is null")]
-    NullParamErr,
-    #[error("fail to generate random bytes")]
-    RandErr,
-    #[error("Unknown currency name")]
-    UnknownCurrencyName,
-    #[error("Unknown language")]
-    UnknownLanguage,
-    #[error("{0}")]
-    Utf8Error(std::str::Utf8Error),
-    #[error("Wrong language")]
-    WrongLanguage,
-}
-
-impl From<io::Error> for DubpError {
-    fn from(e: io::Error) -> Self {
-        Self::IoErr(e)
+pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
+    if c_char_ptr.is_null() {
+        Err(DubpError::NullParamErr)
+    } else {
+        unsafe { CStr::from_ptr(c_char_ptr).to_str() }.map_err(DubpError::Utf8Error)
     }
 }
 
-struct DartRes(allo_isolate::ffi::DartCObject);
-impl IntoDart for DartRes {
-    fn into_dart(self) -> allo_isolate::ffi::DartCObject {
-        self.0.into_dart()
-    }
-}
-impl<E> From<Result<String, E>> for DartRes
-where
-    E: ToString,
-{
-    fn from(res: Result<String, E>) -> Self {
-        match res {
-            Ok(string) => Self(vec![string].into_dart()),
-            Err(e) => Self(vec![String::from("_"), e.to_string()].into_dart()),
-        }
-    }
-}
-impl<E> From<Result<Vec<String>, E>> for DartRes
-where
-    E: ToString,
-{
-    fn from(res: Result<Vec<String>, E>) -> Self {
-        match res {
-            Ok(vec_string) => Self(vec_string.into_dart()),
-            Err(e) => Self(vec![String::with_capacity(0), e.to_string()].into_dart()),
-        }
+fn char_ptr_prt_to_vec_str<'a>(
+    char_ptr_ptr: *const *const raw::c_char,
+    len: u32,
+) -> Result<Vec<&'a str>, DubpError> {
+    let len = len as usize;
+    let char_ptr_slice: &[*const raw::c_char] =
+        unsafe { std::slice::from_raw_parts(char_ptr_ptr, len) };
+    let mut str_vec = Vec::with_capacity(len);
+    for char_ptr in char_ptr_slice {
+        str_vec.push(char_ptr_to_str(*char_ptr)?);
     }
+    Ok(str_vec)
 }
 
-pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
-    if c_char_ptr.is_null() {
-        Err(DubpError::NullParamErr)
-    } else {
-        unsafe { CStr::from_ptr(c_char_ptr).to_str() }.map_err(DubpError::Utf8Error)
+fn u32_to_language(i: u32) -> Result<Language, DubpError> {
+    match i {
+        0 => Ok(Language::English),
+        1 => Ok(Language::French),
+        _ => Err(DubpError::UnknownLanguage),
     }
 }
 
@@ -103,9 +75,17 @@ pub extern "C" fn change_dewif_pin(
     old_pin: *const raw::c_char,
     new_pin: *const raw::c_char,
 ) {
-    Isolate::new(port).post(DartRes::from(dewif::change_pin(
-        currency, dewif, old_pin, new_pin,
-    )));
+    exec_async(
+        port,
+        || {
+            let currency = char_ptr_to_str(currency)?;
+            let dewif = char_ptr_to_str(dewif)?;
+            let old_pin = char_ptr_to_str(old_pin)?;
+            let new_pin = char_ptr_to_str(new_pin)?;
+            Ok((currency, dewif, old_pin, new_pin))
+        },
+        |(currency, dewif, old_pin, new_pin)| dewif::change_pin(currency, dewif, old_pin, new_pin),
+    )
 }
 
 #[no_mangle]
@@ -116,9 +96,16 @@ pub extern "C" fn gen_dewif(
     mnemonic: *const raw::c_char,
     pin: *const raw::c_char,
 ) {
-    Isolate::new(port).post(DartRes::from(dewif::gen_dewif(
-        currency, language, mnemonic, pin,
-    )));
+    exec_async(
+        port,
+        || {
+            let currency = char_ptr_to_str(currency)?;
+            let mnemonic = char_ptr_to_str(mnemonic)?;
+            let pin = char_ptr_to_str(pin)?;
+            Ok((currency, language, mnemonic, pin))
+        },
+        |(currency, language, mnemonic, pin)| dewif::gen_dewif(currency, language, mnemonic, pin),
+    )
 }
 
 #[no_mangle]
@@ -148,7 +135,16 @@ pub extern "C" fn get_dewif_pubkey(
     dewif: *const raw::c_char,
     pin: *const raw::c_char,
 ) {
-    Isolate::new(port).post(DartRes::from(dewif::get_pubkey(currency, dewif, pin)));
+    exec_async(
+        port,
+        || {
+            let currency = char_ptr_to_str(currency)?;
+            let dewif = char_ptr_to_str(dewif)?;
+            let pin = char_ptr_to_str(pin)?;
+            Ok((currency, dewif, pin))
+        },
+        |(currency, dewif, pin)| dewif::get_pubkey(currency, dewif, pin),
+    )
 }
 
 #[no_mangle]
@@ -157,10 +153,14 @@ pub extern "C" fn mnemonic_to_pubkey(
     language: u32,
     mnemonic_phrase: *const raw::c_char,
 ) {
-    Isolate::new(port).post(DartRes::from(mnemonic::mnemonic_to_pubkey(
-        language,
-        mnemonic_phrase,
-    )));
+    exec_async(
+        port,
+        || {
+            let mnemonic_phrase = char_ptr_to_str(mnemonic_phrase)?;
+            Ok((language, mnemonic_phrase))
+        },
+        |(language, mnemonic_phrase)| mnemonic::mnemonic_to_pubkey(language, mnemonic_phrase),
+    )
 }
 
 #[no_mangle]
@@ -171,7 +171,17 @@ pub extern "C" fn sign(
     pin: *const raw::c_char,
     msg: *const raw::c_char,
 ) {
-    Isolate::new(port).post(DartRes::from(dewif::sign(currency, dewif, pin, msg)));
+    exec_async(
+        port,
+        || {
+            let currency = char_ptr_to_str(currency)?;
+            let dewif = char_ptr_to_str(dewif)?;
+            let pin = char_ptr_to_str(pin)?;
+            let msg = char_ptr_to_str(msg)?;
+            Ok((currency, dewif, pin, msg))
+        },
+        |(currency, dewif, pin, msg)| dewif::sign(currency, dewif, pin, msg),
+    )
 }
 
 #[no_mangle]
@@ -180,16 +190,18 @@ pub extern "C" fn sign_several(
     currency: *const raw::c_char,
     dewif: *const raw::c_char,
     pin: *const raw::c_char,
-    msgs_len: usize,
+    msgs_len: u32,
     msgs: *const *const raw::c_char,
 ) {
-    Isolate::new(port).post(dewif::sign_several(currency, dewif, pin, msgs_len, msgs));
-}
-
-fn u32_to_language(i: u32) -> Result<Language, DubpError> {
-    match i {
-        0 => Ok(Language::English),
-        1 => Ok(Language::French),
-        _ => Err(DubpError::UnknownLanguage),
-    }
+    exec_async(
+        port,
+        || {
+            let currency = char_ptr_to_str(currency)?;
+            let dewif = char_ptr_to_str(dewif)?;
+            let pin = char_ptr_to_str(pin)?;
+            let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
+            Ok((currency, dewif, pin, msgs))
+        },
+        |(currency, dewif, pin, msgs)| dewif::sign_several(currency, dewif, pin, &msgs),
+    )
 }
diff --git a/native/dubp_rs/src/mnemonic.rs b/native/dubp_rs/src/mnemonic.rs
index ac17486dbdeb155300812c63b9f6ab6fffda12e6..765427dde2477d365e7b028310eb512a08744cf1 100644
--- a/native/dubp_rs/src/mnemonic.rs
+++ b/native/dubp_rs/src/mnemonic.rs
@@ -21,12 +21,7 @@ pub(super) fn gen_mnemonic(language: u32) -> Result<String, DubpError> {
     Ok(mnemonic.phrase().to_owned())
 }
 
-pub(super) fn mnemonic_to_pubkey(
-    language: u32,
-    mnemonic: *const raw::c_char,
-) -> Result<String, DubpError> {
-    let mnemonic = char_ptr_to_str(mnemonic)?;
-
+pub(super) fn mnemonic_to_pubkey(language: u32, mnemonic: &str) -> Result<String, DubpError> {
     let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
         .map_err(|_| DubpError::WrongLanguage)?;
     let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index a3384e8b9ce4060ab171174f349ff955c88724c2..35b4e8aee25bc3e0aa6c200272cbfec18db91f97 100644
--- a/packages/dubp_rs/lib/dubp.dart
+++ b/packages/dubp_rs/lib/dubp.dart
@@ -55,7 +55,7 @@ class DubpRust {
   static Future<String> genMnemonic({Language language = Language.english}) {
     final completer = Completer<String>();
     final sendPort =
-        singleCompletePort<String, List>(completer, callback: _handleErr);
+        singleCompletePort<String, String>(completer, callback: _handleErr);
     native.gen_mnemonic(
       sendPort.nativePort,
       language.index,
@@ -66,7 +66,7 @@ class DubpRust {
   static Future<String> _genPin(PinLength pinLength) {
     final completer = Completer<String>();
     final sendPort =
-        singleCompletePort<String, List>(completer, callback: _handleErr);
+        singleCompletePort<String, String>(completer, callback: _handleErr);
     switch (pinLength) {
       case PinLength.ten:
         native.gen_pin10(
@@ -101,7 +101,7 @@ class DubpRust {
     {
       final completer = Completer<String>();
       final sendPort =
-          singleCompletePort<String, List>(completer, callback: _handleErr);
+          singleCompletePort<String, String>(completer, callback: _handleErr);
       native.change_dewif_pin(
         sendPort.nativePort,
         Utf8.toUtf8(currency),
@@ -116,7 +116,7 @@ class DubpRust {
     {
       final completer = Completer<String>();
       final sendPort =
-          singleCompletePort<String, List>(completer, callback: _handleErr);
+          singleCompletePort<String, String>(completer, callback: _handleErr);
       native.get_dewif_pubkey(
         sendPort.nativePort,
         Utf8.toUtf8(currency),
@@ -148,7 +148,7 @@ class DubpRust {
     {
       final completer = Completer<String>();
       final sendPort =
-          singleCompletePort<String, List>(completer, callback: _handleErr);
+          singleCompletePort<String, String>(completer, callback: _handleErr);
       native.mnemonic_to_pubkey(
         sendPort.nativePort,
         language.index,
@@ -161,7 +161,7 @@ class DubpRust {
     {
       final completer = Completer<String>();
       final sendPort =
-          singleCompletePort<String, List>(completer, callback: _handleErr);
+          singleCompletePort<String, String>(completer, callback: _handleErr);
       native.gen_dewif(
         sendPort.nativePort,
         Utf8.toUtf8(currency),
@@ -179,7 +179,7 @@ class DubpRust {
       {String currency = "g1", String dewif, String pin}) async {
     final completer = Completer<String>();
     final sendPort =
-        singleCompletePort<String, List>(completer, callback: _handleErr);
+        singleCompletePort<String, String>(completer, callback: _handleErr);
     native.get_dewif_pubkey(
       sendPort.nativePort,
       Utf8.toUtf8(currency),
@@ -196,7 +196,7 @@ class DubpRust {
       {String currency = "g1", String dewif, String pin, String message}) {
     final completer = Completer<String>();
     final sendPort =
-        singleCompletePort<String, List>(completer, callback: _handleErr);
+        singleCompletePort<String, String>(completer, callback: _handleErr);
     native.sign(
       sendPort.nativePort,
       Utf8.toUtf8(currency),
@@ -243,21 +243,20 @@ class DubpRust {
     return ptr;
   }
 
-  static String _handleErr(List res) {
-    final List<String> arr = res.cast();
-    if (arr.length == 1) {
-      return arr[0];
-    } else {
-      final error = arr[1];
+  static String _handleErr(String res) {
+    if (res.startsWith('DUBP_RS_ERROR: ')) {
+      final error = res;
       print(error);
       throw error;
+    } else {
+      return res;
     }
   }
 
   static List<String> _handleErrList(List res) {
     final List<String> arr = res.cast();
-    if (arr.isNotEmpty && arr[0].isEmpty) {
-      final error = arr[1];
+    if (arr.isNotEmpty && arr[0].startsWith('DUBP_RS_ERROR: ')) {
+      final error = arr[0];
       print(error);
       throw error;
     } else {
diff --git a/pubspec.lock b/pubspec.lock
index 376b9d0d629eec0ab26866ecf3c2421def82d63e..844655598d3b9f9e5592335edb3da833717b890a 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -21,42 +21,42 @@ packages:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.5.0-nullsafety.3"
+    version: "2.5.0-nullsafety.1"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.0-nullsafety.3"
+    version: "2.1.0-nullsafety.1"
   characters:
     dependency: transitive
     description:
       name: characters
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety.5"
+    version: "1.1.0-nullsafety.3"
   charcode:
     dependency: transitive
     description:
       name: charcode
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0-nullsafety.3"
+    version: "1.2.0-nullsafety.1"
   clock:
     dependency: transitive
     description:
       name: clock
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety.3"
+    version: "1.1.0-nullsafety.1"
   collection:
     dependency: transitive
     description:
       name: collection
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.15.0-nullsafety.5"
+    version: "1.15.0-nullsafety.3"
   connectivity:
     dependency: transitive
     description:
@@ -112,7 +112,7 @@ packages:
       name: fake_async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0-nullsafety.3"
+    version: "1.2.0-nullsafety.1"
   ffi:
     dependency: transitive
     description:
@@ -282,27 +282,20 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.0.3"
-  js:
-    dependency: transitive
-    description:
-      name: js
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.6.3-nullsafety.3"
   matcher:
     dependency: transitive
     description:
       name: matcher
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.10-nullsafety.3"
+    version: "0.12.10-nullsafety.1"
   meta:
     dependency: transitive
     description:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0-nullsafety.6"
+    version: "1.3.0-nullsafety.3"
   nested:
     dependency: transitive
     description:
@@ -330,7 +323,7 @@ packages:
       name: path
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.0-nullsafety.3"
+    version: "1.8.0-nullsafety.1"
   path_provider:
     dependency: "direct main"
     description:
@@ -468,42 +461,42 @@ packages:
       name: source_span
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.0-nullsafety.4"
+    version: "1.8.0-nullsafety.2"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.10.0-nullsafety.6"
+    version: "1.10.0-nullsafety.1"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.0-nullsafety.3"
+    version: "2.1.0-nullsafety.1"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety.3"
+    version: "1.1.0-nullsafety.1"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0-nullsafety.3"
+    version: "1.2.0-nullsafety.1"
   test_api:
     dependency: transitive
     description:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.2.19-nullsafety.6"
+    version: "0.2.19-nullsafety.2"
   truncate:
     dependency: "direct main"
     description:
@@ -517,7 +510,7 @@ packages:
       name: typed_data
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0-nullsafety.5"
+    version: "1.3.0-nullsafety.3"
   uuid:
     dependency: transitive
     description:
@@ -538,7 +531,7 @@ packages:
       name: vector_math
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.0-nullsafety.5"
+    version: "2.1.0-nullsafety.3"
   websocket:
     dependency: transitive
     description:
@@ -575,5 +568,5 @@ packages:
     source: hosted
     version: "2.2.1"
 sdks:
-  dart: ">=2.12.0-0.0 <3.0.0"
+  dart: ">=2.10.0-110 <2.11.0"
   flutter: ">=1.22.0 <2.0.0"