diff --git a/Cargo.lock b/Cargo.lock
index 69a91e3d7d69f99d5107e4571e388a1bb1e0aed6..8ffe513c7e389617a435ec33f97e3ce0321abbd6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -58,6 +58,12 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
+[[package]]
+name = "assert_matches"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
+
 [[package]]
 name = "async-oneshot"
 version = "0.4.2"
@@ -250,19 +256,21 @@ name = "dubp_rs"
 version = "0.1.0"
 dependencies = [
  "allo-isolate",
+ "assert_matches",
  "cbindgen",
  "dart-bindgen",
  "dup-crypto",
  "fast-threadpool",
  "once_cell",
+ "parking_lot",
  "thiserror",
 ]
 
 [[package]]
 name = "dup-crypto"
-version = "0.44.0"
+version = "0.45.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4281497a99e7bb67d54800671558d707c48ca35320f8c5747fb0eda4d8cbc71"
+checksum = "58a3b88cbd886b092a7e6c58608d87744706e0fc66a48eaf452c297e5aac3802"
 dependencies = [
  "aes",
  "arrayvec",
@@ -272,7 +280,7 @@ dependencies = [
  "byteorder",
  "cryptoxide",
  "ed25519-bip32",
- "getrandom 0.2.2",
+ "getrandom",
  "once_cell",
  "ring",
  "serde",
@@ -326,17 +334,6 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "getrandom"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
-dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
-]
-
 [[package]]
 name = "getrandom"
 version = "0.2.2"
@@ -345,7 +342,7 @@ checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
- "wasi 0.10.2+wasi-snapshot-preview1",
+ "wasi",
 ]
 
 [[package]]
@@ -372,6 +369,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "instant"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
 [[package]]
 name = "itoa"
 version = "0.4.7"
@@ -439,6 +445,31 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 
+[[package]]
+name = "parking_lot"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
+dependencies = [
+ "cfg-if 1.0.0",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.10"
@@ -465,11 +496,10 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.7.3"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
 dependencies = [
- "getrandom 0.1.16",
  "libc",
  "rand_chacha",
  "rand_core",
@@ -478,9 +508,9 @@ dependencies = [
 
 [[package]]
 name = "rand_chacha"
-version = "0.2.2"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
 dependencies = [
  "ppv-lite86",
  "rand_core",
@@ -488,27 +518,30 @@ dependencies = [
 
 [[package]]
 name = "rand_core"
-version = "0.5.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
 dependencies = [
- "getrandom 0.1.16",
+ "getrandom",
 ]
 
 [[package]]
 name = "rand_hc"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
 dependencies = [
  "rand_core",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.57"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
+checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
+dependencies = [
+ "bitflags",
+]
 
 [[package]]
 name = "remove_dir_all"
@@ -577,6 +610,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "smallvec"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
+
 [[package]]
 name = "spin"
 version = "0.5.2"
@@ -629,11 +668,11 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.1.0"
+version = "3.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "libc",
  "rand",
  "redox_syscall",
@@ -721,12 +760,6 @@ version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
 
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
 [[package]]
 name = "wasi"
 version = "0.10.2+wasi-snapshot-preview1"
diff --git a/native/dubp_rs/Cargo.toml b/native/dubp_rs/Cargo.toml
index 6468d2e7d093ba5bf1b26a378c834d206a6b007a..b27959de42dbb73aa4e2424b297bb730708bb2fe 100644
--- a/native/dubp_rs/Cargo.toml
+++ b/native/dubp_rs/Cargo.toml
@@ -11,11 +11,15 @@ crate-type = ["rlib"]
 
 [dependencies]
 allo-isolate = "0.1.6"
-dup-crypto = { version = "0.44.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "scrypt"] }
+dup-crypto = { version = "0.45.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "scrypt"] }
 fast-threadpool = { version = "0.3.0", default-features = false }
 once_cell = { version = "1.3.1", default-features = false, features = ["std"] }
+parking_lot = "0.11.1"
 thiserror = "1.0.24"
 
 [build-dependencies]
 cbindgen = "0.14.3"
-dart-bindgen = "0.1.7"
\ No newline at end of file
+dart-bindgen = "0.1.7"
+
+[dev-dependencies]
+assert_matches = "1.5.0"
diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs
index c05ad85d1152027c82861e9aabca096a1f42c532..63252a323beff80df0047e0fd4349cae2bde7aff 100644
--- a/native/dubp_rs/src/dewif.rs
+++ b/native/dubp_rs/src/dewif.rs
@@ -81,22 +81,38 @@ pub(super) fn get_dewif_meta(
 }
 
 pub(super) fn get_pubkey(
+    account_index_opt: Option<u32>,
+    address_index_opt: Option<U31>,
     currency: Currency,
     dewif: &str,
+    external_opt: Option<bool>,
     secret_code: &str,
 ) -> Result<String, DubpError> {
-    let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
-        ExpectedCurrency::Specific(currency),
-        dewif,
-        &secret_code.to_ascii_uppercase(),
-    )
-    .map_err(DubpError::DewifReadError)?;
-
-    match keypairs.next() {
-        Some(KeyPairEnum::Ed25519(keypair)) => Ok(keypair.public_key().to_base58()),
-        Some(KeyPairEnum::Bip32Ed25519(_)) => Err(DubpError::GetMasterPubkeyOfHdWallet),
-        Some(_) => Err(DubpError::UnsupportedDewifVersion),
-        None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
+    if let Some(account_index) = account_index_opt {
+        dewif::bip32::get_bip32_pubkey(
+            account_index,
+            address_index_opt,
+            currency,
+            dewif,
+            external_opt,
+            secret_code,
+        )
+    } else if address_index_opt.is_none() && external_opt.is_none() {
+        let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
+            ExpectedCurrency::Specific(currency),
+            dewif,
+            &secret_code.to_ascii_uppercase(),
+        )
+        .map_err(DubpError::DewifReadError)?;
+
+        match keypairs.next() {
+            Some(KeyPairEnum::Ed25519(keypair)) => Ok(keypair.public_key().to_base58()),
+            Some(KeyPairEnum::Bip32Ed25519(_)) => Err(DubpError::GetMasterPubkeyOfHdWallet),
+            Some(_) => Err(DubpError::UnsupportedDewifVersion),
+            None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
+        }
+    } else {
+        Err(DubpError::GiveExternalBoolOrAddressIndexForLegacyWallet)
     }
 }
 
@@ -126,3 +142,51 @@ pub(crate) fn log_n(system_memory: i64) -> u8 {
         12
     }
 }
+
+pub(super) fn sign(
+    account_index_opt: Option<u32>,
+    address_index_opt: Option<U31>,
+    currency: Currency,
+    dewif: &str,
+    external_opt: Option<bool>,
+    secret_code: &str,
+    msg: &str,
+) -> Result<String, DubpError> {
+    if let Some(account_index) = account_index_opt {
+        dewif::bip32::sign_bip32(
+            account_index,
+            address_index_opt,
+            currency,
+            dewif,
+            external_opt,
+            secret_code,
+            msg,
+        )
+    } else {
+        dewif::classic::sign(currency, dewif, secret_code, msg)
+    }
+}
+
+pub(super) fn sign_several(
+    account_index_opt: Option<u32>,
+    address_index_opt: Option<U31>,
+    currency: Currency,
+    dewif: &str,
+    external_opt: Option<bool>,
+    secret_code: &str,
+    msgs: &[&str],
+) -> Result<Vec<String>, DubpError> {
+    if let Some(account_index) = account_index_opt {
+        dewif::bip32::sign_several_bip32(
+            account_index,
+            address_index_opt,
+            currency,
+            dewif,
+            external_opt,
+            secret_code,
+            msgs,
+        )
+    } else {
+        dewif::classic::sign_several(currency, dewif, secret_code, msgs)
+    }
+}
diff --git a/native/dubp_rs/src/dewif/bip32.rs b/native/dubp_rs/src/dewif/bip32.rs
index 1fa982cb29938ddf412cde55dcbb9b648ab10ce3..e5392852a52205ba54b2636380966039fe2ffa17 100644
--- a/native/dubp_rs/src/dewif/bip32.rs
+++ b/native/dubp_rs/src/dewif/bip32.rs
@@ -15,30 +15,24 @@
 
 use crate::*;
 
-const MEMBER_ACCOUNT_INDEX: u32 = 0;
+#[derive(Debug)]
+struct OpaqueAccount {
+    address_index: u32,
+    chain_code: ChainCode,
+    public_key: PublicKey,
+}
+
+static CHAINING_EXTERNAL_PUBKEYS: Lazy<Arc<Mutex<HashMap<u32, OpaqueAccount>>>> =
+    Lazy::new(|| Arc::new(Mutex::new(HashMap::new())));
 
 pub(crate) fn get_accounts_pubkeys(
     currency: Currency,
     dewif: &str,
     secret_code: &str,
-    accounts_indexs: Vec<DerivationIndex>,
+    accounts_indexs: Vec<U31>,
 ) -> Result<Vec<String>, DubpError> {
-    if accounts_indexs.contains(
-        &DerivationIndex::hard(MEMBER_ACCOUNT_INDEX).map_err(DubpError::InvalidDerivationIndex)?,
-    ) {
-        if crate::secret_code::is_ascii_letters(secret_code) {
-            let log_n =
-                dup_crypto::dewif::read_dewif_log_n(ExpectedCurrency::Specific(currency), dewif)
-                    .map_err(DubpError::DewifReadError)?;
-            let expected_secret_code_len =
-                crate::secret_code::compute_secret_code_len(true, SecretCodeType::Letters, log_n)?;
-
-            if secret_code.len() < expected_secret_code_len {
-                return Err(DubpError::SecretCodeTooShort);
-            }
-        } else {
-            return Err(DubpError::InvalidSecretCodeType);
-        }
+    if accounts_indexs.contains(&U31::new(0)?) {
+        verify_member_secret_code(currency, dewif, secret_code)?;
     }
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
@@ -50,25 +44,109 @@ pub(crate) fn get_accounts_pubkeys(
         Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => Ok(accounts_indexs
             .into_iter()
             .map(|account_index| {
-                master_keypair
-                    .derive(account_index)
-                    .public_key()
-                    .to_base58()
+                PrivateDerivationPath::transparent(account_index)
+                    .map(|path| master_keypair.derive(path).public_key().to_base58())
             })
-            .collect()),
+            .collect::<Result<Vec<_>, InvalidAccountIndex>>()?),
+        Some(_) => Err(DubpError::NotHdWallet),
+        None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
+    }
+}
+
+pub(crate) fn get_bip32_pubkey(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    currency: Currency,
+    dewif: &str,
+    external_opt: Option<bool>,
+    secret_code: &str,
+) -> Result<String, DubpError> {
+    let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
+        ExpectedCurrency::Specific(currency),
+        dewif,
+        &secret_code.to_ascii_uppercase(),
+    )
+    .map_err(DubpError::DewifReadError)?;
+
+    if account_index == 0 {
+        verify_member_secret_code(currency, dewif, secret_code)?;
+    }
+
+    match keypairs.next() {
+        Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => get_bip32_pubkey_inner(
+            account_index,
+            address_index_opt,
+            external_opt,
+            master_keypair,
+        ),
         Some(_) => Err(DubpError::NotHdWallet),
         None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
     }
 }
 
-pub(crate) fn sign_transparent(
-    account_index: DerivationIndex,
-    currency: &str,
+pub(crate) fn get_opaque_account_next_external_address(
+    account_index: U31,
+) -> Result<String, DubpError> {
+    let mut guard = CHAINING_EXTERNAL_PUBKEYS.lock();
+    if let Some(opaque_account) = guard.get_mut(&account_index.into_u32()) {
+        let next_address = PublicKeyWithChainCode {
+            chain_code: opaque_account.chain_code,
+            public_key: opaque_account.public_key,
+        }
+        .derive(U31::new(opaque_account.address_index).expect("unreachable"))
+        .expect("unreachable")
+        .public_key;
+
+        opaque_account.address_index += 1;
+
+        Ok(next_address.to_base58())
+    } else {
+        Err(DubpError::OpaqueAccountNotLoaded)
+    }
+}
+
+pub(crate) fn load_opaque_bip32_accounts(
+    accounts_indexs: Vec<U31>,
+    currency: Currency,
     dewif: &str,
     secret_code: &str,
+) -> Result<(), DubpError> {
+    let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
+        ExpectedCurrency::Specific(currency),
+        dewif,
+        &secret_code.to_ascii_uppercase(),
+    )
+    .map_err(DubpError::DewifReadError)?;
+    match keypairs.next() {
+        Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => {
+            for account_index in accounts_indexs {
+                let external_path = PrivateDerivationPath::opaque(account_index, true, None)?;
+                let external_kp = master_keypair.derive(external_path);
+                let opaque_account = OpaqueAccount {
+                    address_index: 0,
+                    public_key: external_kp.public_key(),
+                    chain_code: external_kp.chain_code(),
+                };
+
+                let mut guard = CHAINING_EXTERNAL_PUBKEYS.lock();
+                guard.insert(account_index.into_u32(), opaque_account);
+            }
+            Ok(())
+        }
+        Some(_) => Err(DubpError::NotHdWallet),
+        None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
+    }
+}
+
+pub(crate) fn sign_bip32(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    currency: Currency,
+    dewif: &str,
+    external_opt: Option<bool>,
+    secret_code: &str,
     msg: &str,
 ) -> Result<String, DubpError> {
-    let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
         dewif,
@@ -76,25 +154,32 @@ pub(crate) fn sign_transparent(
     )
     .map_err(DubpError::DewifReadError)?;
 
+    if account_index == 0 {
+        verify_member_secret_code(currency, dewif, secret_code)?;
+    }
+
     match keypairs.next() {
-        Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => Ok(master_keypair
-            .derive(account_index)
-            .generate_signator()
-            .sign(msg.as_bytes())
-            .to_base64()),
+        Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => sign_bip32_inner(
+            account_index,
+            address_index_opt,
+            external_opt,
+            master_keypair,
+            msg,
+        ),
         Some(_) => Err(DubpError::NotHdWallet),
         None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
     }
 }
 
-pub(crate) fn sign_several_transparent(
-    account_index: DerivationIndex,
-    currency: &str,
+pub(crate) fn sign_several_bip32(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    currency: Currency,
     dewif: &str,
+    external_opt: Option<bool>,
     secret_code: &str,
     msgs: &[&str],
 ) -> Result<Vec<String>, DubpError> {
-    let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
         dewif,
@@ -102,15 +187,206 @@ pub(crate) fn sign_several_transparent(
     )
     .map_err(DubpError::DewifReadError)?;
 
+    if account_index == 0 {
+        verify_member_secret_code(currency, dewif, secret_code)?;
+    }
+
     match keypairs.next() {
-        Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => {
-            let signator = master_keypair.derive(account_index).generate_signator();
-            Ok(msgs
-                .iter()
-                .map(|msg| signator.sign(msg.as_bytes()).to_base64())
-                .collect())
-        }
+        Some(KeyPairEnum::Bip32Ed25519(master_keypair)) => sign_several_bip32_inner(
+            account_index,
+            address_index_opt,
+            external_opt,
+            master_keypair,
+            msgs,
+        ),
         Some(_) => Err(DubpError::NotHdWallet),
         None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)),
     }
 }
+
+fn get_bip32_pubkey_inner(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    external_opt: Option<bool>,
+    master_keypair: KeyPair,
+) -> Result<String, DubpError> {
+    Ok(master_keypair
+        .derive(z_get_derivation_path(
+            account_index,
+            address_index_opt,
+            external_opt,
+        )?)
+        .public_key()
+        .to_base58())
+}
+
+fn sign_bip32_inner(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    external_opt: Option<bool>,
+    master_keypair: KeyPair,
+    msg: &str,
+) -> Result<String, DubpError> {
+    Ok(master_keypair
+        .derive(z_get_derivation_path(
+            account_index,
+            address_index_opt,
+            external_opt,
+        )?)
+        .generate_signator()
+        .sign(msg.as_bytes())
+        .to_base64())
+}
+
+fn sign_several_bip32_inner(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    external_opt: Option<bool>,
+    master_keypair: KeyPair,
+    msgs: &[&str],
+) -> Result<Vec<String>, DubpError> {
+    let signator = master_keypair
+        .derive(z_get_derivation_path(
+            account_index,
+            address_index_opt,
+            external_opt,
+        )?)
+        .generate_signator();
+
+    Ok(msgs
+        .iter()
+        .map(|msg| signator.sign(msg.as_bytes()).to_base64())
+        .collect())
+}
+
+fn verify_member_secret_code(
+    currency: Currency,
+    dewif: &str,
+    secret_code: &str,
+) -> Result<(), DubpError> {
+    if crate::secret_code::is_ascii_letters(secret_code) {
+        let log_n =
+            dup_crypto::dewif::read_dewif_log_n(ExpectedCurrency::Specific(currency), dewif)
+                .map_err(DubpError::DewifReadError)?;
+        let expected_secret_code_len =
+            crate::secret_code::compute_secret_code_len(true, SecretCodeType::Letters, log_n)?;
+
+        if secret_code.len() < expected_secret_code_len {
+            Err(DubpError::SecretCodeTooShort)
+        } else {
+            Ok(())
+        }
+    } else {
+        Err(DubpError::InvalidSecretCodeType)
+    }
+}
+
+fn z_get_derivation_path(
+    account_index: u32,
+    address_index_opt: Option<U31>,
+    external_opt: Option<bool>,
+) -> Result<PrivateDerivationPath, DubpError> {
+    let account_index_u31 = U31::new(account_index)?;
+    match account_index % 3 {
+        0 => Ok(PrivateDerivationPath::transparent(account_index_u31)?),
+        1 => {
+            if let Some(external) = external_opt {
+                if external {
+                    if address_index_opt.is_none() {
+                        Ok(PrivateDerivationPath::semi_opaque_external(
+                            account_index_u31,
+                        )?)
+                    } else {
+                        Err(DubpError::InvalidAccountIndex(InvalidAccountIndex))
+                    }
+                } else if address_index_opt.is_some() {
+                    Ok(PrivateDerivationPath::semi_opaque_internal(
+                        account_index_u31,
+                        address_index_opt,
+                    )?)
+                } else {
+                    Err(DubpError::TryToSignWithInternalChainingAddress)
+                }
+            } else {
+                Err(DubpError::MissingExternalBool)
+            }
+        }
+        2 => {
+            if address_index_opt.is_some() {
+                if let Some(external) = external_opt {
+                    Ok(PrivateDerivationPath::opaque(
+                        account_index_u31,
+                        external,
+                        address_index_opt,
+                    )?)
+                } else {
+                    Err(DubpError::MissingExternalBool)
+                }
+            } else {
+                Err(DubpError::TryToSignWithChainingAddress)
+            }
+        }
+        _ => unreachable!(),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use assert_matches::assert_matches;
+
+    const MNEMONIC: &str =
+        "tongue cute mail fossil great frozen same social weasel impact brush kind";
+
+    #[test]
+    fn test_get_accounts_pubkeys() -> Result<(), DubpError> {
+        let vec = crate::dewif::gen_dewif(
+            "g1",
+            Language::English,
+            MNEMONIC,
+            false,
+            SecretCodeType::Letters,
+            1_000,
+        )?;
+        let dewif = &vec[0];
+        let secret_code = &vec[1];
+        //println!("TMP: secret_code={}", secret_code);
+
+        assert_matches!(
+            get_accounts_pubkeys(
+                Currency::from(G1_CURRENCY),
+                dewif,
+                secret_code,
+                vec![U31::new(0).expect("unreachable")],
+            ),
+            Err(DubpError::SecretCodeTooShort)
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_sign_bip32() {
+        assert_matches!(
+            z_get_derivation_path(1, None, None),
+            Err(DubpError::MissingExternalBool)
+        );
+        assert_matches!(
+            z_get_derivation_path(2, None, None),
+            Err(DubpError::TryToSignWithChainingAddress)
+        );
+        assert_matches!(z_get_derivation_path(3, None, None), Ok(_));
+        assert_matches!(
+            z_get_derivation_path(1, None, Some(false)),
+            Err(DubpError::TryToSignWithInternalChainingAddress)
+        );
+        assert_matches!(
+            z_get_derivation_path(2, None, Some(true)),
+            Err(DubpError::TryToSignWithChainingAddress)
+        );
+        assert_matches!(
+            z_get_derivation_path(1, Some(U31::new(5).expect("unreachable")), Some(true),),
+            Err(DubpError::InvalidAccountIndex(_))
+        );
+    }
+}
diff --git a/native/dubp_rs/src/dewif/classic.rs b/native/dubp_rs/src/dewif/classic.rs
index dcfd97af853da725e89b16fd4a5fa5c121b76369..a0e23f8d6eb8dd920250b99ed4b3c230875d128f 100644
--- a/native/dubp_rs/src/dewif/classic.rs
+++ b/native/dubp_rs/src/dewif/classic.rs
@@ -16,12 +16,11 @@
 use crate::*;
 
 pub(crate) fn sign(
-    currency: &str,
+    currency: Currency,
     dewif: &str,
     secret_code: &str,
     msg: &str,
 ) -> Result<String, DubpError> {
-    let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
         dewif,
@@ -36,12 +35,11 @@ pub(crate) fn sign(
 }
 
 pub(crate) fn sign_several(
-    currency: &str,
+    currency: Currency,
     dewif: &str,
     secret_code: &str,
     msgs: &[&str],
 ) -> Result<Vec<String>, DubpError> {
-    let currency = parse_currency(currency)?;
     let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
         ExpectedCurrency::Specific(currency),
         dewif,
diff --git a/native/dubp_rs/src/error.rs b/native/dubp_rs/src/error.rs
index 33f60a6a7d563b7fa8974e2dd718e090861f73d6..29a48bceafeed2b3764a050a18868c3d50e5a1e3 100644
--- a/native/dubp_rs/src/error.rs
+++ b/native/dubp_rs/src/error.rs
@@ -13,8 +13,6 @@
 // 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 dup_crypto::keys::ed25519::bip32::InvalidDerivationIndex;
-
 use crate::*;
 
 /// Dubp error
@@ -26,20 +24,30 @@ pub(crate) enum DubpError {
     DigitsCodeForbidForMemberWallet,
     #[error("It is forbidden to retrieve the master public key of an HD wallet.")]
     GetMasterPubkeyOfHdWallet,
+    #[error("Give external bool or address index for legacy wallet.")]
+    GiveExternalBoolOrAddressIndexForLegacyWallet,
     #[error("I/O error: {0}")]
     IoErr(io::Error),
     #[error("{0}")]
-    InvalidDerivationIndex(InvalidDerivationIndex),
+    InvalidAccountIndex(InvalidAccountIndex),
+    #[error("{0}")]
+    InvalidU31(U31Error),
     #[error("Invalid secret code type")]
     InvalidSecretCodeType,
+    #[error("Missing external bool")]
+    MissingExternalBool,
     #[error("this wallet is not an HD wallet")]
     NotHdWallet,
-    #[error("this account index is not a transparent account index")]
-    NotTransparentAccountIndex,
     #[error("A given parameter is null")]
     NullParamErr,
+    #[error("Opaque account not loaded")]
+    OpaqueAccountNotLoaded,
     #[error("Secret code too short: please change your secret code")]
     SecretCodeTooShort,
+    #[error("The chaining address cannot be used to sign with opaque account")]
+    TryToSignWithChainingAddress,
+    #[error("The internal chaining address cannot be used to sign with semi-opaque account")]
+    TryToSignWithInternalChainingAddress,
     #[error("fail to generate random bytes")]
     RandErr,
     #[error("Unknown currency name")]
@@ -60,9 +68,15 @@ impl From<io::Error> for DubpError {
     }
 }
 
-impl From<InvalidDerivationIndex> for DubpError {
-    fn from(e: InvalidDerivationIndex) -> Self {
-        Self::InvalidDerivationIndex(e)
+impl From<InvalidAccountIndex> for DubpError {
+    fn from(e: InvalidAccountIndex) -> Self {
+        Self::InvalidAccountIndex(e)
+    }
+}
+
+impl From<U31Error> for DubpError {
+    fn from(e: U31Error) -> Self {
+        Self::InvalidU31(e)
     }
 }
 
@@ -77,6 +91,17 @@ impl IntoDart for DartRes {
         self.0.into_dart()
     }
 }
+impl<E> From<Result<(), E>> for DartRes
+where
+    E: ToString,
+{
+    fn from(res: Result<(), E>) -> Self {
+        match res {
+            Ok(()) => Self("".into_dart()),
+            Err(e) => Self(format!("DUBP_RS_ERROR: {}", e.to_string()).into_dart()),
+        }
+    }
+}
 impl<E> From<Result<String, E>> for DartRes
 where
     E: ToString,
diff --git a/native/dubp_rs/src/inputs.rs b/native/dubp_rs/src/inputs.rs
index 31ecf378324bd37bc1cd9fc4baf81c6ed5519203..4aeaee9fb4b6a0fbf35aecae52d7b506aa38e4a2 100644
--- a/native/dubp_rs/src/inputs.rs
+++ b/native/dubp_rs/src/inputs.rs
@@ -52,13 +52,13 @@ pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a
     }
 }
 
-pub(crate) fn char_ptr_prt_to_vec_hard_derivation_index(
+pub(crate) fn char_ptr_prt_to_vec_u31(
     u32_ptr: *const u32,
     len: u32,
-) -> Result<Vec<DerivationIndex>, DubpError> {
+) -> Result<Vec<U31>, DubpError> {
     u32_ptr_to_vec_u32(u32_ptr, len)
         .into_iter()
-        .map(|ai| DerivationIndex::hard(ai).map_err(DubpError::InvalidDerivationIndex))
+        .map(|ai| U31::new(ai).map_err(DubpError::InvalidU31))
         .collect()
 }
 
@@ -76,6 +76,30 @@ pub(crate) fn char_ptr_prt_to_vec_str<'a>(
     Ok(str_vec)
 }
 
+pub(crate) fn i32_to_opt_bool(i: i32) -> Option<bool> {
+    match i {
+        1 => Some(true),
+        0 => Some(false),
+        _ => None,
+    }
+}
+
+pub(crate) fn i32_to_opt_u31(i: i32) -> Result<Option<U31>, DubpError> {
+    if i >= 0 {
+        Ok(Some(U31::new(i as u32)?))
+    } else {
+        Ok(None)
+    }
+}
+
+pub(crate) fn i32_to_opt_u32(i: i32) -> Option<u32> {
+    if i >= 0 {
+        Some(i as u32)
+    } else {
+        None
+    }
+}
+
 pub(crate) fn parse_currency(currency: &str) -> Result<Currency, DubpError> {
     let currency_code = match currency {
         "g1" => G1_CURRENCY,
@@ -85,14 +109,6 @@ pub(crate) fn parse_currency(currency: &str) -> Result<Currency, DubpError> {
     Ok(Currency::from(currency_code))
 }
 
-pub(crate) fn transparent_account_index(account_index: u32) -> Result<DerivationIndex, DubpError> {
-    if account_index % 3 == 0 {
-        DerivationIndex::hard(account_index).map_err(DubpError::InvalidDerivationIndex)
-    } else {
-        Err(DubpError::NotTransparentAccountIndex)
-    }
-}
-
 pub(crate) fn u32_ptr_to_vec_u32(u32_ptr: *const u32, len: u32) -> Vec<u32> {
     let len = len as usize;
     let u32_slice: &[u32] = unsafe { std::slice::from_raw_parts(u32_ptr, len) };
diff --git a/native/dubp_rs/src/legacy.rs b/native/dubp_rs/src/legacy.rs
index 45aef12b8698916195144a620cf2f5113e397662..92bb737fc1a7cd9cbbbceed3d8667d66c9eb72b4 100644
--- a/native/dubp_rs/src/legacy.rs
+++ b/native/dubp_rs/src/legacy.rs
@@ -42,14 +42,6 @@ pub(super) fn get_pubkey(salt: &str, password: &str) -> String {
         .to_base58()
 }
 
-pub(super) fn sign(salt: &str, password: &str, msg: &str) -> String {
-    KeyPairFromSaltedPasswordGenerator::with_default_parameters()
-        .generate(SaltedPassword::new(salt.to_owned(), password.to_owned()))
-        .generate_signator()
-        .sign(msg.as_bytes())
-        .to_base64()
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -73,7 +65,14 @@ mod tests {
         assert_eq!(get_pubkey("salt", "pass"), pubkey.to_owned());
 
         assert_eq!(
-            crate::dewif::get_pubkey(Currency::from(G1_CURRENCY), &dewif, &secret_code)?,
+            crate::dewif::get_pubkey(
+                None,
+                None,
+                Currency::from(G1_CURRENCY),
+                &dewif,
+                None,
+                &secret_code
+            )?,
             pubkey.to_owned()
         );
 
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 544d1c412bd8d57dc8ee7df90dff159a4577fd3a..92b8091205d2b9b696dae193f1cf4ef180948611 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -32,14 +32,19 @@ use dup_crypto::{
     bases::b58::ToBase58,
     dewif::{Currency, DewifReadError, ExpectedCurrency, G1_CURRENCY, G1_TEST_CURRENCY},
     keys::{
-        ed25519::bip32::DerivationIndex, ed25519::KeyPairFromSeed32Generator, KeyPair as _,
-        KeyPairEnum, Signator as _, Signature as _,
+        ed25519::bip32::{
+            ChainCode, InvalidAccountIndex, KeyPair, PrivateDerivationPath, PublicKeyWithChainCode,
+        },
+        ed25519::{KeyPairFromSeed32Generator, PublicKey},
+        KeyPair as _, KeyPairEnum, Signator as _, Signature as _,
     },
     mnemonic::{Language, Mnemonic, MnemonicType},
+    utils::{U31Error, U31},
 };
 use fast_threadpool::{ThreadPool, ThreadPoolConfig, ThreadPoolSyncHandler};
 use once_cell::sync::Lazy;
-use std::{ffi::CStr, io, os::raw};
+use parking_lot::Mutex;
+use std::{collections::HashMap, ffi::CStr, io, os::raw, sync::Arc};
 use thiserror::Error;
 
 #[no_mangle]
@@ -163,6 +168,30 @@ pub extern "C" fn gen_mnemonic(port: i64, language: u32) {
     exec_async(port, || u32_to_language(language), mnemonic::gen_mnemonic)
 }
 
+#[no_mangle]
+pub extern "C" fn get_bip32_dewif_accounts_pubkeys(
+    port: i64,
+    currency: *const raw::c_char,
+    dewif: *const raw::c_char,
+    secret_code: *const raw::c_char,
+    accounts_indexs_len: u32,
+    accounts_indexs: *const u32,
+) {
+    exec_async(
+        port,
+        || {
+            let currency = parse_currency(char_ptr_to_str(currency)?)?;
+            let dewif = char_ptr_to_str(dewif)?;
+            let secret_code = char_ptr_to_str(secret_code)?;
+            let accounts_indexs = char_ptr_prt_to_vec_u31(accounts_indexs, accounts_indexs_len)?;
+            Ok((currency, dewif, secret_code, accounts_indexs))
+        },
+        |(currency, dewif, secret_code, accounts_indexs)| {
+            dewif::bip32::get_accounts_pubkeys(currency, dewif, secret_code, accounts_indexs)
+        },
+    )
+}
+
 #[no_mangle]
 pub extern "C" fn get_dewif_meta(
     port: i64,
@@ -201,43 +230,76 @@ pub extern "C" fn get_dewif_secret_code_len(
 #[no_mangle]
 pub extern "C" fn get_dewif_pubkey(
     port: i64,
+    account_index: i32,
+    address_index: i32,
     currency: *const raw::c_char,
     dewif: *const raw::c_char,
+    external_opt: i32,
     pin: *const raw::c_char,
 ) {
     exec_async(
         port,
         || {
+            let account_index_opt = i32_to_opt_u32(account_index);
+            let address_index_opt = i32_to_opt_u31(address_index)?;
             let currency = parse_currency(char_ptr_to_str(currency)?)?;
             let dewif = char_ptr_to_str(dewif)?;
+            let external_opt = i32_to_opt_bool(external_opt);
             let pin = char_ptr_to_str(pin)?;
-            Ok((currency, dewif, pin))
+            Ok((
+                account_index_opt,
+                address_index_opt,
+                currency,
+                dewif,
+                external_opt,
+                pin,
+            ))
+        },
+        |(account_index_opt, address_index_opt, currency, dewif, external_opt, pin)| {
+            dewif::get_pubkey(
+                account_index_opt,
+                address_index_opt,
+                currency,
+                dewif,
+                external_opt,
+                pin,
+            )
         },
-        |(currency, dewif, pin)| dewif::get_pubkey(currency, dewif, pin),
     )
 }
 
 #[no_mangle]
-pub extern "C" fn get_bip32_dewif_accounts_pubkeys(
+pub extern "C" fn get_opaque_account_next_external_address(port: i64, account_index: u32) {
+    exec_async(
+        port,
+        || {
+            let account_index = U31::new(account_index)?;
+            Ok(account_index)
+        },
+        dewif::bip32::get_opaque_account_next_external_address,
+    )
+}
+
+#[no_mangle]
+pub extern "C" fn load_opaque_bip32_accounts(
     port: i64,
+    accounts_indexs_len: u32,
+    accounts_indexs: *const u32,
     currency: *const raw::c_char,
     dewif: *const raw::c_char,
     secret_code: *const raw::c_char,
-    accounts_indexs_len: u32,
-    accounts_indexs: *const u32,
 ) {
     exec_async(
         port,
         || {
+            let accounts_indexs = char_ptr_prt_to_vec_u31(accounts_indexs, accounts_indexs_len)?;
             let currency = parse_currency(char_ptr_to_str(currency)?)?;
             let dewif = char_ptr_to_str(dewif)?;
             let secret_code = char_ptr_to_str(secret_code)?;
-            let accounts_indexs =
-                char_ptr_prt_to_vec_hard_derivation_index(accounts_indexs, accounts_indexs_len)?;
-            Ok((currency, dewif, secret_code, accounts_indexs))
+            Ok((accounts_indexs, currency, dewif, secret_code))
         },
-        |(currency, dewif, secret_code, accounts_indexs)| {
-            dewif::bip32::get_accounts_pubkeys(currency, dewif, secret_code, accounts_indexs)
+        |(accounts_indexs, currency, dewif, secret_code)| {
+            dewif::bip32::load_opaque_bip32_accounts(accounts_indexs, currency, dewif, secret_code)
         },
     )
 }
@@ -279,112 +341,106 @@ pub extern "C" fn mnemonic_to_pubkey(
 #[no_mangle]
 pub extern "C" fn sign(
     port: i64,
+    account_index: i32,
+    address_index: i32,
     currency: *const raw::c_char,
     dewif: *const raw::c_char,
-    pin: *const raw::c_char,
-    msg: *const raw::c_char,
-) {
-    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::classic::sign(currency, dewif, pin, msg),
-    )
-}
-
-#[no_mangle]
-pub extern "C" fn sign_bip32_transparent(
-    port: i64,
-    account_index: u32,
-    currency: *const raw::c_char,
-    dewif: *const raw::c_char,
+    external_opt: i32,
     secret_code: *const raw::c_char,
     msg: *const raw::c_char,
 ) {
     exec_async(
         port,
         || {
-            let account_index = transparent_account_index(account_index)?;
-            let currency = char_ptr_to_str(currency)?;
+            let account_index_opt = i32_to_opt_u32(account_index);
+            let address_index_opt = i32_to_opt_u31(address_index)?;
+            let currency = parse_currency(char_ptr_to_str(currency)?)?;
             let dewif = char_ptr_to_str(dewif)?;
-            let pin = char_ptr_to_str(secret_code)?;
+            let external_opt = i32_to_opt_bool(external_opt);
+            let secret_code = char_ptr_to_str(secret_code)?;
             let msg = char_ptr_to_str(msg)?;
-            Ok((currency, dewif, pin, msg, account_index))
-        },
-        |(currency, dewif, secret_code, msg, account_index)| {
-            dewif::bip32::sign_transparent(account_index, currency, dewif, secret_code, msg)
+            Ok((
+                account_index_opt,
+                address_index_opt,
+                currency,
+                dewif,
+                external_opt,
+                secret_code,
+                msg,
+            ))
         },
-    )
-}
-
-#[no_mangle]
-pub extern "C" fn sign_legacy(
-    port: i64,
-    salt: *const raw::c_char,
-    password: *const raw::c_char,
-    msg: *const raw::c_char,
-) {
-    exec_async(
-        port,
-        || {
-            let salt = char_ptr_to_str(salt)?;
-            let password = char_ptr_to_str(password)?;
-            let msg = char_ptr_to_str(msg)?;
-            Ok((salt, password, msg))
+        |(
+            account_index_opt,
+            address_index_opt,
+            currency,
+            dewif,
+            external_opt,
+            secret_code,
+            msg,
+        )| {
+            dewif::sign(
+                account_index_opt,
+                address_index_opt,
+                currency,
+                dewif,
+                external_opt,
+                secret_code,
+                msg,
+            )
         },
-        |(salt, password, msg)| Ok::<_, DubpError>(legacy::sign(salt, password, msg)),
     )
 }
 
 #[no_mangle]
 pub extern "C" fn sign_several(
     port: i64,
+    account_index: i32,
+    address_index: i32,
     currency: *const raw::c_char,
     dewif: *const raw::c_char,
-    pin: *const raw::c_char,
-    msgs_len: u32,
-    msgs: *const *const raw::c_char,
-) {
-    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::classic::sign_several(currency, dewif, pin, &msgs),
-    )
-}
-
-#[no_mangle]
-pub extern "C" fn sign_several_bip32_transparent(
-    port: i64,
-    account_index: u32,
-    currency: *const raw::c_char,
-    dewif: *const raw::c_char,
-    pin: *const raw::c_char,
+    external_opt: i32,
+    secret_code: *const raw::c_char,
     msgs_len: u32,
     msgs: *const *const raw::c_char,
 ) {
     exec_async(
         port,
         || {
-            let account_index = transparent_account_index(account_index)?;
-            let currency = char_ptr_to_str(currency)?;
+            let account_index_opt = i32_to_opt_u32(account_index);
+            let address_index_opt = i32_to_opt_u31(address_index)?;
+            let currency = parse_currency(char_ptr_to_str(currency)?)?;
             let dewif = char_ptr_to_str(dewif)?;
-            let pin = char_ptr_to_str(pin)?;
+            let external_opt = i32_to_opt_bool(external_opt);
+            let secret_code = char_ptr_to_str(secret_code)?;
             let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
-            Ok((currency, dewif, pin, msgs, account_index))
+            Ok((
+                account_index_opt,
+                address_index_opt,
+                currency,
+                dewif,
+                external_opt,
+                secret_code,
+                msgs,
+            ))
         },
-        |(currency, dewif, pin, msgs, account_index)| {
-            dewif::bip32::sign_several_transparent(account_index, currency, dewif, pin, &msgs)
+        |(
+            account_index_opt,
+            address_index_opt,
+            currency,
+            dewif,
+            external_opt,
+            secret_code,
+            msgs,
+        )| {
+            dewif::sign_several(
+                account_index_opt,
+                address_index_opt,
+                currency,
+                dewif,
+                external_opt,
+                secret_code,
+                &msgs,
+            )
         },
     )
 }
diff --git a/packages/dubp_rs/README.md b/packages/dubp_rs/README.md
index 958eb82c4309552a2a58792ab4fa66385dd953e1..6be3629b994c6e05ff9ff36ecb9f123aa0031139 100644
--- a/packages/dubp_rs/README.md
+++ b/packages/dubp_rs/README.md
@@ -144,10 +144,12 @@ NewWallet new_wallet = await DubpRust.genWalletFromMnemonic(
 #### Function signature
 
 ```dart
-static Future<String> signBip32Transparent({
+static Future<String> sign({
     int accountIndex,
+    int addressIndexOpt,
     String currency = "g1",
     String dewif,
+    bool externalOpt,
     String secretCode,
     String message
 });
@@ -158,7 +160,7 @@ If the wallet is not dedicated to the Äž1 currency, you must indicate the curren
 #### Usage example
 
 ```dart
-String signature = await DubpRust.signBip32Transparent(
+String signature = await DubpRust.sign(
     accountIndex: 3,
     dewif: "AAAAARAAAAGfFDAs+jVZYkfhBlHZZ2fEQIvBqnG16g5+02cY18wSOjW0cUg2JV3SUTJYN2CrbQeRDwGazWnzSFBphchMmiL0",
     pin: "CDJ4UB",
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index ee4ee9bdf16f827aca80d7cc00b4428b36345824..94382c7fb63a8620aaf72b6c0000675393d59490 100644
--- a/packages/dubp_rs/lib/dubp.dart
+++ b/packages/dubp_rs/lib/dubp.dart
@@ -177,7 +177,16 @@ class DubpRust {
     return Future.value(NewWallet._(newWallet[0], newWallet[1]));
   }
 
-  //get_bip32_dewif_accounts_pubkeys
+  /// Get next external public key of a specific opaque account
+  static Future<String> getOpaqueAccountNextExternalPublicKey(
+      {int accountIndex}) async {
+    final completer = Completer<String>();
+    final sendPort =
+        singleCompletePort<String, String>(completer, callback: _handleErr);
+    native.get_opaque_account_next_external_address(
+        sendPort.nativePort, accountIndex.toUnsigned(31));
+    return completer.future;
+  }
 
   /// Get BIP32 accounts public keys (in base 58) of `dewif` master keypair.
   static Future<List<String>> getBip32DewifAccountsPublicKeys(
@@ -194,7 +203,7 @@ class DubpRust {
         Utf8.toUtf8(dewif),
         Utf8.toUtf8(secretCode),
         accountsIndex.length,
-        _listIntToPtr(accountsIndex));
+        _listIntToPtrUint32(accountsIndex));
     return completer.future;
   }
 
@@ -215,14 +224,26 @@ class DubpRust {
 
   /// Get public key (in base 58) of `dewif` keypair.
   static Future<String> getDewifPublicKey(
-      {String currency = "g1", String dewif, String pin}) async {
+      {int accountIndexOpt,
+      int addressIndexOpt,
+      String currency = "g1",
+      String dewif,
+      bool externalOpt,
+      String pin}) async {
+    var externalOptInt = -1;
+    if (externalOpt != null) {
+      externalOptInt = externalOpt ? 1 : 0;
+    }
     final completer = Completer<String>();
     final sendPort =
         singleCompletePort<String, String>(completer, callback: _handleErr);
     native.get_dewif_pubkey(
       sendPort.nativePort,
+      accountIndexOpt ?? -1,
+      addressIndexOpt ?? -1,
       Utf8.toUtf8(currency),
       Utf8.toUtf8(dewif),
+      externalOptInt,
       Utf8.toUtf8(pin),
     );
     return completer.future;
@@ -261,70 +282,91 @@ class DubpRust {
     return completer.future;
   }
 
-  /// Sign the message `message` with `dewif` Bip32-Ed25519 keypair encryted
+  /// Load opaque accounts
+  static Future<void> loadOpaqueAccounts(
+    List<int> accountsIndex,
+    String currency,
+    String dewif,
+    String secretCode,
+  ) {
+    final completer = Completer<void>();
+    final sendPort =
+        singleCompletePort<void, String>(completer, callback: _handleErrVoid);
+    native.load_opaque_bip32_accounts(
+        sendPort.nativePort,
+        accountsIndex.length,
+        _listIntToPtrUint32(accountsIndex),
+        Utf8.toUtf8(currency),
+        Utf8.toUtf8(dewif),
+        Utf8.toUtf8(secretCode));
+    return completer.future;
+  }
+
+  /// Sign the message `message` with `dewif` keypair encryted
   /// in DEWIF format.
   ///
-  /// If you have several messages to sign, use `signSeveralBip32Transparent`
+  /// If you have several messages to sign, use `signSeveral`
   /// method instead.
-  static Future<String> signBip32Transparent(
-      {int accountIndex,
+  static Future<String> sign(
+      {int accountIndexOpt,
+      int addressIndexOpt,
       String currency = "g1",
       String dewif,
+      bool externalOpt,
       String secretCode,
       String message}) {
+    var externalOptInt = -1;
+    if (externalOpt != null) {
+      externalOptInt = externalOpt ? 1 : 0;
+    }
+
     final completer = Completer<String>();
     final sendPort =
         singleCompletePort<String, String>(completer, callback: _handleErr);
-    native.sign_bip32_transparent(
+    native.sign(
       sendPort.nativePort,
-      accountIndex,
+      accountIndexOpt ?? -1,
+      addressIndexOpt ?? -1,
       Utf8.toUtf8(currency),
       Utf8.toUtf8(dewif),
+      externalOptInt,
       Utf8.toUtf8(secretCode),
       Utf8.toUtf8(message),
     );
     return completer.future;
   }
 
-  /// Sign the message `message` with legacy wallet (password + salt)
-  ///
-  /// This deprecated method must be used only for compatibility purpose !
-  static Future<String> signLegacy(
-      {String password, String salt, String message}) {
-    final completer = Completer<String>();
-    final sendPort =
-        singleCompletePort<String, String>(completer, callback: _handleErr);
-    native.sign_legacy(
-      sendPort.nativePort,
-      Utf8.toUtf8(password),
-      Utf8.toUtf8(salt),
-      Utf8.toUtf8(message),
-    );
-    return completer.future;
-  }
-
   /// Sign several messages `messages` with `dewif` keypair encryted in DEWIF
   /// format.
   ///
   /// This method is optimized to sign several messages at once. If you have
   /// several messages to sign, avoid calling the `sign` method for each
   /// message. Use this `signSeveral` method instead.
-  static Future<List<String>> signSeveralBip32Transparent(
-      {int accountIndex,
+  static Future<List<String>> signSeveral(
+      {int accountIndexOpt,
+      int addressIndexOpt,
       String currency = "g1",
       String dewif,
-      String pin,
+      bool externalOpt,
+      String secretCode,
       List<String> messages}) {
+    var externalOptInt = -1;
+    if (externalOpt != null) {
+      externalOptInt = externalOpt ? 1 : 0;
+    }
+
     final completer = Completer<List<String>>();
     final sendPort = singleCompletePort<List<String>, List>(completer,
         callback: _handleErrList);
 
-    native.sign_several_bip32_transparent(
+    native.sign_several(
       sendPort.nativePort,
-      accountIndex,
+      accountIndexOpt ?? -1,
+      addressIndexOpt ?? -1,
       Utf8.toUtf8(currency),
       Utf8.toUtf8(dewif),
-      Utf8.toUtf8(pin),
+      externalOptInt,
+      Utf8.toUtf8(secretCode),
       messages.length,
       _listStringToPtr(messages),
     );
@@ -332,11 +374,11 @@ class DubpRust {
     return completer.future;
   }
 
-  static Pointer<Uint32> _listIntToPtr(List<int> list) {
-    //final listUint32 = list.map(int.toUnsigned).toList();
-    final Pointer<Uint32> ptr = allocate(count: list.length);
-    for (var i = 0; i < list.length; i++) {
-      ptr[i] = list[i];
+  static Pointer<Uint32> _listIntToPtrUint32(List<int> list) {
+    final listUint32 = list.map((i) => i.toUnsigned(31)).toList();
+    final Pointer<Uint32> ptr = allocate(count: listUint32.length);
+    for (var i = 0; i < listUint32.length; i++) {
+      ptr[i] = listUint32[i];
     }
     return ptr;
   }
@@ -371,6 +413,14 @@ class DubpRust {
     }
   }
 
+  static void _handleErrVoid(String res) {
+    if (res.startsWith('DUBP_RS_ERROR: ')) {
+      final error = res;
+      print(error);
+      throw error;
+    }
+  }
+
   /*static int _handleErrInt(String res) {
     if (res.startsWith('DUBP_RS_ERROR: ')) {
       final error = res;