diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 1dc6f214a4a529180ca25ce4ad5edf27c0e022ac..8e8fca2d4fe4e71d43dd22e2a7186f6092f984c6 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,6 +3,8 @@ Changelog
 0.23.4
 ------
 * Bip39 and Bip32 support has been added
+* Privatekey derivation based on Bip39/Bip22 has been added
+* Several unit tests have been added
 
 0.23.3
 ------
diff --git a/beemgraphenebase/__init__.py b/beemgraphenebase/__init__.py
index 54d00b2e6684ad3692c27a30a4f024ff5a09259d..487c905f10355d430333de3a4cb423d87a636f66 100644
--- a/beemgraphenebase/__init__.py
+++ b/beemgraphenebase/__init__.py
@@ -9,6 +9,7 @@ from .version import version as __version__
 
 __all__ = ['account',
            'base58',
+           'bip32'
            'bip38',
            'transactions',
            'types',
diff --git a/beemgraphenebase/account.py b/beemgraphenebase/account.py
index 90d22c7373cf3d399590047574a944d6f6635151..3bcc17db9fd5bec62e792c0a993fec0059b1569d 100644
--- a/beemgraphenebase/account.py
+++ b/beemgraphenebase/account.py
@@ -22,6 +22,7 @@ from binascii import hexlify, unhexlify
 import unicodedata
 
 from .base58 import ripemd160, Base58
+from .bip32 import BIP32Key, parse_path
 from .dictionary import words as BrainKeyDictionary
 from .dictionary import words_bip39 as MnemonicDictionary
 from .py23 import py23_bytes, PY2
@@ -176,11 +177,17 @@ class BrainKey(object):
 # Copyright (c) 2017 mruddy
 @python_2_unicode_compatible
 class Mnemonic(object):
+    """BIP39 mnemoric implementation"""
     def __init__(self):
         self.wordlist = MnemonicDictionary.split(',')
-        self.radix = 2048 
+        self.radix = 2048
 
     def generate(self, strength=128):
+        """ Generates a word list based on the given strength
+
+        :param int strength: initial entropy strength, must be one of [128, 160, 192, 224, 256]
+
+        """
         if strength not in [128, 160, 192, 224, 256]:
             raise ValueError(
                 "Strength should be one of the following [128, 160, 192, 224, 256], but it is not (%d)."
@@ -267,6 +274,10 @@ class Mnemonic(object):
         return result_phrase
 
     def check(self, mnemonic):
+        """ Checks the mnemonic word list is valid
+        :param list mnemonic: mnemonic word list with lenght of 12, 15, 18, 21, 24
+        :returns: True, when valid
+        """
         mnemonic = self.normalize_string(mnemonic).split(" ")
         # list of valid mnemonic lengths
         if len(mnemonic) not in [12, 15, 18, 21, 24]:
@@ -284,6 +295,11 @@ class Mnemonic(object):
         return h == nh
 
     def expand_word(self, prefix):
+        """Expands a word when sufficient chars are given
+
+        :param str prefix: first chars of a valid dict word
+
+        """
         if prefix in self.wordlist:
             return prefix
         else:
@@ -296,10 +312,12 @@ class Mnemonic(object):
                 return prefix
 
     def expand(self, mnemonic):
+        """Expands all words given in a list"""
         return " ".join(map(self.expand_word, mnemonic.split(" ")))
 
     @classmethod
     def normalize_string(cls, txt):
+        """Normalizes strings"""
         if isinstance(txt, str if sys.version < "3" else bytes):
             utxt = txt.decode("utf8")
         elif isinstance(txt, unicode if sys.version < "3" else str):  # noqa: F821
@@ -311,6 +329,12 @@ class Mnemonic(object):
 
     @classmethod
     def to_seed(cls, mnemonic, passphrase=""):
+        """Returns a seed based on bip39
+
+        :param str mnemonic: string containing a valid mnemonic word list
+        :param str passphrase: optional, passphrase can be set to modify the returned seed.
+        
+        """
         mnemonic = cls.normalize_string(mnemonic)
         passphrase = cls.normalize_string(passphrase)
         passphrase = "mnemonic" + passphrase
@@ -320,6 +344,54 @@ class Mnemonic(object):
         return stretched[:64]
 
 
+
+
+class MnemonicKey(object):
+    """ This class derives a private key from a BIP39 mnemoric implementation
+    """
+
+    def __init__(self, word_list, passphrase="", role="active", account_number=0, sequence=0, prefix="STM"):
+        mnemonic = Mnemonic()
+        self.seed = mnemonic.to_seed(word_list, passphrase=passphrase)
+        self.role = role
+        self.account_number = account_number
+        self.sequence = sequence
+        self.prefix = prefix
+        self.path_prefix = "m/48'/13'"
+
+    def get_path(self):
+        if self.account_number < 0:
+            raise ValueError("sequence must be >= 0")
+        if self.sequence < 0:
+            raise ValueError("account_number must be >= 0")
+        if self.role == "owner":
+            return "%s/0'/%d'/%d'" % (self.path_prefix, self.account_number, self.sequence)
+        elif self.role == "active":
+            return "%s/1'/%d'/%d'" % (self.path_prefix, self.account_number, self.sequence)
+        elif self.role == "posting":
+            return "%s/4'/%d'/%d'" % (self.path_prefix, self.account_number, self.sequence)
+        elif self.role == "memo":
+            return "%s/3'/%d'/%d'" % (self.path_prefix, self.account_number, self.sequence)
+        raise ValueError("Wrong role")
+
+    def get_private(self):
+        """ Derive private key from the account_number, the role and the sequence
+        """
+        key = BIP32Key.fromEntropy(self.seed)
+        for n in parse_path(self.get_path()):
+            key = key.ChildKey(n)
+        return PrivateKey(key.WalletImportFormat(), prefix=self.prefix)
+
+    def get_public(self):
+        return self.get_private().pubkey
+
+    def get_private_key(self):
+        return self.get_private()
+
+    def get_public_key(self):
+        return self.get_public()
+
+
 @python_2_unicode_compatible
 class Address(object):
     """ Address class
diff --git a/beemgraphenebase/base58.py b/beemgraphenebase/base58.py
index 7cd2256899391cbfdb8427f234a64f871864753f..b4cf72487dffc6ab5d915c5cc2c336855a183a5f 100644
--- a/beemgraphenebase/base58.py
+++ b/beemgraphenebase/base58.py
@@ -192,13 +192,16 @@ def base58CheckEncode(version, payload):
     return base58encode(result)
 
 
-def base58CheckDecode(s):
+def base58CheckDecode(s, skip_first_bytes=True):
     s = unhexlify(base58decode(s))
     dec = hexlify(s[:-4]).decode('ascii')
     checksum = doublesha256(dec)[:4]
     if not (s[-4:] == checksum):
         raise AssertionError()
-    return dec[2:]
+    if skip_first_bytes:
+        return dec[2:]
+    else:
+        return dec
 
 
 def gphBase58CheckEncode(s):
diff --git a/beemgraphenebase/bip32.py b/beemgraphenebase/bip32.py
index 99e9c2a637c7ab8336c2c2c416c15f069b300c82..3e1ffe8ba75605cae1ce048a41cb606739d0450c 100644
--- a/beemgraphenebase/bip32.py
+++ b/beemgraphenebase/bip32.py
@@ -75,7 +75,7 @@ class BIP32Key(object):
         """
         # Sanity checks
         # raw = check_decode(xkey)
-        raw = b'\x04' + unhexlify(base58CheckDecode(xkey))
+        raw = unhexlify(base58CheckDecode(xkey, skip_first_bytes=False))
         
         if len(raw) != 78:
             raise ValueError("extended key format wrong length")
diff --git a/tests/beem/test_cli.py b/tests/beem/test_cli.py
index 4db91caea9f24d59d863043524a47150b3cd1cca..9e736dcbd0176be4d47b23b82f69176ba9b39d78 100644
--- a/tests/beem/test_cli.py
+++ b/tests/beem/test_cli.py
@@ -455,9 +455,9 @@ class Testcases(unittest.TestCase):
         self.assertEqual(result.exit_code, 0)
         result = runner.invoke(cli, ['pending', '--post', '--comment', account_name])
         self.assertEqual(result.exit_code, 0)
-        result = runner.invoke(cli, ['pending', '--post', '--comment', '--curation', '--permlink', '--days', '1', account_name])
+        result = runner.invoke(cli, ['pending', '--curation', '--permlink', '--days', '1', account_name])
         self.assertEqual(result.exit_code, 0)
-        result = runner.invoke(cli, ['pending', '--post', '--comment', '--curation', '--author', '--permlink', '--length', '30', '--days', '1', account_name])
+        result = runner.invoke(cli, ['pending', '--post', '--comment', '--author', '--permlink', '--length', '30', '--days', '1', account_name])
         self.assertEqual(result.exit_code, 0)
         result = runner.invoke(cli, ['pending', '--post', '--author', '--title', '--days', '1', account_name])
         self.assertEqual(result.exit_code, 0)
diff --git a/tests/beemgraphene/test_account.py b/tests/beemgraphene/test_account.py
index 4122940d4b32f409850c259e96eb2371b4092e5a..c1d0bfb0ed643863e358da1fb91ce620b087d38f 100644
--- a/tests/beemgraphene/test_account.py
+++ b/tests/beemgraphene/test_account.py
@@ -7,7 +7,7 @@ from builtins import str
 import unittest
 from beemgraphenebase.base58 import Base58, base58encode
 from beemgraphenebase.bip32 import BIP32Key
-from beemgraphenebase.account import BrainKey, Address, PublicKey, PrivateKey, PasswordKey, Mnemonic
+from beemgraphenebase.account import BrainKey, Address, PublicKey, PrivateKey, PasswordKey, Mnemonic, MnemonicKey
 from binascii import hexlify, unhexlify
 import sys
 import hashlib
@@ -452,3 +452,29 @@ class Testcases(unittest.TestCase):
         m = Mnemonic()
         for d in data:
             self.assertEqual(m.to_entropy(m.to_mnemonic(d).split()), d)
+
+    def test_mnemorickey(self):
+        word_list = "news clever spot drama infant detail sword cover color throw foot primary when slender rhythm clog autumn ecology enough bronze math you modify excuse"
+        mk = MnemonicKey(word_list, role="owner")
+        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L2cgypn75kre1s7JUkTK6H7Y656GwDbNnSNZKWSQ2Rnnx6qM11KD")))
+        self.assertEqual(str(mk.get_public_key()), str(PublicKey("02821aa2d26c4fd9b735dd1fed148b96fec978eae1440adf79a4bf95e118b2d8f1")))
+        
+        mk = MnemonicKey(word_list, role="owner", sequence=5)
+        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L5cJSZPcBMBtmuRaK9C48yyXK5JpaH15BsjKLZkmamEWKKx25Kx7")))
+        self.assertEqual(str(mk.get_public_key()), str(PublicKey("0309a45aa9add2c7421e0553e23b1800e51d95e525fa4eae1bcc5fb58186e07ed5")))
+
+        mk = MnemonicKey(word_list, role="owner", account_number=2)
+        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L4A95nfp1kyJtUtaTqzMyLQkz6NYSfk4R8pejcgKXQSUtPysiFgv")))
+        self.assertEqual(str(mk.get_public_key()), str(PublicKey("02b164dc8819830cd50fca4217ad35fa7371cf29db1bc6a07456cc0090ca8ea8fe")))
+
+        mk = MnemonicKey(word_list, role="active")
+        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("KygWePihetfhKYCHahcHjMebNSy53HtcXkccYuTn6R8QLydyPUWt")))
+        self.assertEqual(str(mk.get_public_key()), str(PublicKey("035c679454155c4c41e8956ecb8e514d37d2d28da91db81c3a22f216a09af94605")))
+
+        mk = MnemonicKey(word_list, role="posting")
+        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L53K986B756VbqatsCi3jjPLHCq8Y38AZyXf19w6CcxuGH84Rrhs")))
+        self.assertEqual(str(mk.get_public_key()), str(PublicKey("0200e7d987dfd5aaecf822420475ddcbadc8503a99893d50d06f87da48e85a8206")))
+
+        mk = MnemonicKey(word_list, role="memo")
+        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L5GrFqdRsroM1Ym4aMdALQBL7xN9kNMru9JTgtwbHVZ4iGvx1184")))
+        self.assertEqual(str(mk.get_public_key()), str(PublicKey("02fa2cdf5a007b01b1911615a4fba9c2a864a1c1ed079d222e5d549d207412c601")))
diff --git a/tests/beemgraphene/test_bip32.py b/tests/beemgraphene/test_bip32.py
index 46555285a65af085ab9a71e2fa57431e0e8f612a..db6c8363364ac0c53a8166276f4c50cf4af8f04b 100644
--- a/tests/beemgraphene/test_bip32.py
+++ b/tests/beemgraphene/test_bip32.py
@@ -113,6 +113,56 @@ class Testcases(unittest.TestCase):
         self.assertEqual(m.ExtendedKey(), "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76")
         self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy")
 
+    def test_vector2(self):
+        seed = unhexlify("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
+        key = BIP32Key.fromEntropy(seed)     
+        self.assertEqual(key.ExtendedKey(), "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U")
+        self.assertEqual(key.ExtendedKey(private=False), "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB")
+        
+        path = "m/0"
+        m = key
+        for n in parse_path(path):
+            m = m.ChildKey(n)
+        self.assertEqual(m.ExtendedKey(), "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt")
+        self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH")
+
+        path = "m/0/2147483647'"
+        m = key
+        for n in parse_path(path):
+            m = m.ChildKey(n)
+        self.assertEqual(m.ExtendedKey(), "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9")
+        self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a")
+        path = "m/0/2147483647'/1"
+        m = key
+        for n in parse_path(path):
+            m = m.ChildKey(n)
+        self.assertEqual(m.ExtendedKey(), "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef")
+        self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon")
+        path = "m/0/2147483647'/1/2147483646'"
+        m = key
+        for n in parse_path(path):
+            m = m.ChildKey(n)
+        self.assertEqual(m.ExtendedKey(), "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc")
+        self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL")
+        path = "m/0/2147483647'/1/2147483646'/2"
+        m = key
+        for n in parse_path(path):
+            m = m.ChildKey(n)
+        self.assertEqual(m.ExtendedKey(), "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j")
+        self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt")
+
+    def test_vector3(self):
+        seed = unhexlify("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be")
+        key = BIP32Key.fromEntropy(seed)     
+        self.assertEqual(key.ExtendedKey(), "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6")
+        self.assertEqual(key.ExtendedKey(private=False), "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13")
+        
+        path = "m/0'"
+        m = key
+        for n in parse_path(path):
+            m = m.ChildKey(n)
+        self.assertEqual(m.ExtendedKey(), "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L")
+        self.assertEqual(m.ExtendedKey(private=False, encoded=True), "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y")
 
 if __name__ == '__main__':
     unittest.main()