From 448c096f1015e4236c8647bd3d35510b86bf3d38 Mon Sep 17 00:00:00 2001 From: Alex Ramirez Date: Tue, 22 Nov 2022 08:44:11 -0500 Subject: [PATCH] feat: Implement from secret (#22) * feat: Implement from secret * test: Add test for Keypair from_secret * test: Add more test for from_secret * test: Add more mnemonic tests --- src/kinetic_sdk/models/keypair.py | 37 +++++++++++++++++++++--- tests/keypair_sdk_test.py | 47 +++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/kinetic_sdk/models/keypair.py b/src/kinetic_sdk/models/keypair.py index b080ab1..4c3a47c 100644 --- a/src/kinetic_sdk/models/keypair.py +++ b/src/kinetic_sdk/models/keypair.py @@ -11,7 +11,6 @@ class Keypair(object): def __init__(self): - self.keypair = SolanaKeypair() self.mnemonic = Keypair.generate_mnemonic() self.keypair = SolanaKeypair.from_solders(Keypair.from_mnemonic(str(self.mnemonic))) @@ -26,7 +25,9 @@ def generate_mnemonic(strength: int = 128): @staticmethod def from_mnemonic(mnemonic_phrase: Union[str, Mnemonic]): - return Keypair.from_mnemonic_set(str(mnemonic_phrase))[0] + keypair = Keypair.from_mnemonic_set(str(mnemonic_phrase))[0] + keypair.mnemonic = mnemonic_phrase + return keypair @staticmethod @@ -43,6 +44,8 @@ def from_mnemonic_set(mnemonic_phrase: Union[str, Mnemonic], fr = 0, to = 2): @staticmethod def from_byte_array(key): + if (type(key) is str): + return SolanaKeypair.from_secret_key(Keypair.to_bytes_array(key)) return SolanaKeypair.from_secret_key(key) @@ -54,14 +57,40 @@ def from_secret_key(key): @staticmethod def random(): return SolanaKeypair() - + + @staticmethod + def from_secret(secret): + keypair: SolanaKeypair = None + if(Keypair.is_mnemonic(secret)): + keypair = Keypair.from_mnemonic(secret) + elif(Keypair.is_byte_array(secret)): + keypair = Keypair.from_byte_array(secret) + else: + keypair = SolanaKeypair.from_secret_key(secret) + + if(keypair is None): + raise Exception("Invalid secret") + + return keypair + + @staticmethod + def is_mnemonic(secret): + return len(str(secret).split(" ")) in [12, 24] + + + @staticmethod + def is_byte_array(secret): + return str(secret).startswith("[") and secret.endswith("]") + @staticmethod def from_solders(keypair: SoldersKeypair): return SolanaKeypair.from_solders(keypair) - @staticmethod def to_solders(self): return self.keypair.to_solders() + def to_bytes_array(secret): + secret = secret.replace("[", "").replace("]", "").split(", ") + return [eval(i) for i in secret] diff --git a/tests/keypair_sdk_test.py b/tests/keypair_sdk_test.py index d37545a..3a62322 100644 --- a/tests/keypair_sdk_test.py +++ b/tests/keypair_sdk_test.py @@ -1,5 +1,6 @@ from kinetic_sdk import KineticSdk from kinetic_sdk.models.keypair import Keypair +import base64 sdk = KineticSdk.setup( @@ -8,13 +9,31 @@ index=1 ) +TEST_MNEMONIC_12 = 'pill tomorrow foster begin walnut borrow virtual kick shift mutual shoe scatter' +TEST_MNEMONIC_12_KEYPAIR = { + 'mnemonic': TEST_MNEMONIC_12, + 'public_key': '5F86TNSTre3CYwZd1wELsGQGhqG2HkN3d8zxhbyBSnzm', + 'secret_key': 'cWNhG6WhR4q6X5v8d65x6UgVR4buQJFkpKVvKiFDbbbZnoxpTJZLoCkCLZXpCYKc1QgyXYbhQpACYN8VKgS5xxq', +} + + +TEST_MNEMONIC_24 = 'grab amused tattoo cruise industry corn welcome wealth tilt erupt gauge ankle remove toast journey heavy unit vibrant zoo blood notice jealous gesture cargo' +TEST_MNEMONIC_24_KEYPAIR = { + 'mnemonic': TEST_MNEMONIC_24, + 'public_key': '6pFBagvvyvBHuCkbMAiPTLn42nnHXrHC2zwWSdZ1NtVn', + 'secret_key': 'WTqijcBccatWsAA6WJzaqgNzJVdARiBHceL5DQG15RbZCNn9jeoEjwMyKRiQqsPvLKGhgkQMoUgo2ybbZmStU3r', +} + def test_keypair_from_mnemonic(): """ Test recovering a Keypair from mnemonic """ - TEST_MNEMONIC_PUBLIC_KEY = "5ZWj7a1f8tWkjBESHKgrLmXshuXxqeY9SYcfbshpAqPG" - TEST_MNEMONIC_12 = 'pill tomorrow foster begin walnut borrow virtual kick shift mutual shoe scatter' keypair = Keypair.from_mnemonic(TEST_MNEMONIC_12) - # assert str(keypair.public_key) == TEST_MNEMONIC_PUBLIC_KEY + assert keypair.mnemonic == TEST_MNEMONIC_12 + assert str(keypair.public_key) == TEST_MNEMONIC_12_KEYPAIR['public_key'] + + keypair = Keypair.from_mnemonic(TEST_MNEMONIC_24) + assert keypair.mnemonic == TEST_MNEMONIC_24 + assert str(keypair.public_key) == TEST_MNEMONIC_24_KEYPAIR['public_key'] def test_keypair_generate_mnemonic(): @@ -49,4 +68,26 @@ def test_mnemonic_derivation_path(): TEST_MNEMONIC_12 = 'field pool drill reward habit engine useless mind hybrid tiny lamp key' TEST_MNEMONIC_PUBLIC_KEY = '9Qrp2PXZSBuWf7CoFd2TMYS4ohUBt12p8rD8wF2W2owD' keypair = Keypair.from_mnemonic(TEST_MNEMONIC_12) + kp_from_secret = Keypair.from_secret(TEST_MNEMONIC_12) assert str(keypair.public_key) == TEST_MNEMONIC_PUBLIC_KEY + assert kp_from_secret.secret_key == keypair.secret_key + assert kp_from_secret.public_key == keypair.public_key + + +def test_keypair_from_secret(): + """ Test recovering a Keypair from secret """ + solanaKeypair = Keypair() + kp1 = solanaKeypair.keypair._solders + + from_byte_array = Keypair.from_secret(f"{kp1.to_solders().to_bytes_array()}") + assert from_byte_array.secret_key == kp1.secret_key + assert from_byte_array.public_key == kp1.public_key + + from_mnemonic = Keypair.from_secret(solanaKeypair.mnemonic) + assert from_mnemonic.secret_key == kp1.secret_key + assert from_mnemonic.public_key == kp1.public_key + assert from_mnemonic.mnemonic == solanaKeypair.mnemonic + + from_secret_key = Keypair.from_secret(kp1.secret_key) + assert from_secret_key.secret_key == kp1.secret_key + assert from_secret_key.public_key == kp1.public_key