diff --git a/aeternity/identifiers.py b/aeternity/identifiers.py index ca3b0756..099cfc7d 100644 --- a/aeternity/identifiers.py +++ b/aeternity/identifiers.py @@ -56,6 +56,10 @@ TRANSACTION ]) +# Account address encoding formats +ACCOUNT_API_FORMAT = 'api' +ACCOUNT_SOFIA_FORMAT = 'sofia' +ACCOUNT_RAW_FORMAT = 'raw' # RLP Identifiers diff --git a/aeternity/signing.py b/aeternity/signing.py index aa82f298..71f66f37 100644 --- a/aeternity/signing.py +++ b/aeternity/signing.py @@ -9,11 +9,11 @@ from nacl.exceptions import CryptoError from nacl.pwhash import argon2id from nacl import secret, utils as nacl_utils -from aeternity.identifiers import ACCOUNT_ID - - +from aeternity.identifiers import ACCOUNT_ID, ACCOUNT_API_FORMAT, ACCOUNT_SOFIA_FORMAT, ACCOUNT_RAW_FORMAT from aeternity import hashing, utils +from deprecated import deprecated + class Account: """Implement private/public key functionalities""" @@ -25,15 +25,40 @@ def __init__(self, signing_key, verifying_key): self.address = hashing.encode(ACCOUNT_ID, pub_key) self.nonce = 0 - def get_address(self): - """get the keypair public_key base58 encoded and prefixed (ak_...)""" - return self.address + def get_address(self, format=ACCOUNT_API_FORMAT): + """ + Get the account address + :param format: the format of the address, possible values are 'api', 'sofia', 'raw', default is 'api' + + when the format is: + - api the address is base58 encoded with ak_ as prefix + - sofia the addres is hex encoded with 0x as prefix + - raw the address is returned as a byte array + + raise ValueError when the format is not recognized + """ + if format == ACCOUNT_API_FORMAT or format is None: + return self.address + elif format == ACCOUNT_RAW_FORMAT: + return self.verifying_key.encode() + elif format == ACCOUNT_SOFIA_FORMAT: + return f'0x{self.verifying_key.encode(encoder=HexEncoder).decode("utf-8")}' + raise ValueError(f'Unrecognized format {format} for address encoding') + @deprecated(version='2.0.0', reason="Use get_secret_key instead") def get_private_key(self): - """get the private key hex encoded""" - pk = self.signing_key.encode(encoder=HexEncoder).decode('utf-8') - pb = self.verifying_key.encode(encoder=HexEncoder).decode('utf-8') - return f"{pk}{pb}" + """ + Get the private key hex encoded + """ + return self.get_secret_key() + + def get_secret_key(self) -> str: + """ + Get the secret key as a hex encoded string + """ + sk = self.signing_key.encode(encoder=HexEncoder).decode('utf-8') + pk = self.verifying_key.encode(encoder=HexEncoder).decode('utf-8') + return f"{sk}{pk}" def sign(self, data): """ diff --git a/requirements.txt b/requirements.txt index c5307ed7..79f147d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,4 @@ websocket_client==0.48.0 validators==0.12.1 semver==2.8.1 namedtupled==0.3.3 +Deprecated==1.2.5 diff --git a/setup.py b/setup.py index f0e50c03..0ad053a2 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,8 @@ def get_version(): 'websocket_client == 0.48.0', 'validators == 0.12.1', 'semver==2.8.1', - 'namedtupled==0.3.3' + 'namedtupled==0.3.3', + 'Deprecated==1.2.5' ], classifiers=[ 'Programming Language :: Python', diff --git a/tests/test_signing.py b/tests/test_signing.py index 81e59c4b..b659fa77 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -2,7 +2,7 @@ from tests import TEST_TTL from aeternity.signing import Account, is_signature_valid from aeternity.utils import is_valid_hash -from aeternity import hashing +from aeternity import hashing, identifiers import os @@ -96,3 +96,15 @@ def test_signing_is_signature_valid(): hashing._base64_decode(account_b64), hashing._base64_decode(sg_b64), msg) + + +def test_signing_get_address(): + a = Account.from_private_key_string( + '3960180c89e27fcc1559f631d664a4b56b569aa5768ba827ddc9ba9616fecd9d8134464ef14b1433790e259d40b6ad8ca39f397a2bbc5261eeba1018a67ce35a') + assert(a.get_address() == 'ak_yuMB5S3yiTwRVJC1NcNEGppcGAbq26qFWNJTCJWnLqoihCpCG') + assert(a.get_address(format=identifiers.ACCOUNT_API_FORMAT) == 'ak_yuMB5S3yiTwRVJC1NcNEGppcGAbq26qFWNJTCJWnLqoihCpCG') + assert(a.get_address(format=identifiers.ACCOUNT_API_FORMAT) != 'ak_xuMB5S3yiTwRVJC1NcNEGppcGAbq26qFWNJTCJWnLqoihCpCG') + assert(a.get_address(format=identifiers.ACCOUNT_SOFIA_FORMAT) == '0x8134464ef14b1433790e259d40b6ad8ca39f397a2bbc5261eeba1018a67ce35a') + assert(a.get_address(format=identifiers.ACCOUNT_SOFIA_FORMAT) != '8134464ef14b1433790e259d40b6ad8ca39f397a2bbc5261eeba1018a67ce35a') + assert(a.get_address(format=identifiers.ACCOUNT_RAW_FORMAT) == b'\x814FN\xf1K\x143y\x0e%\x9d@\xb6\xad\x8c\xa3\x9f9z+\xbcRa\xee\xba\x10\x18\xa6|\xe3Z') + assert(a.get_address(format=identifiers.ACCOUNT_RAW_FORMAT) != b'\x814FN\xf1K\x143y\x0e%\x9d@\xb6\x00\x8c\xa3\x9f9z+\xbcRa\xee\xba\x10\x18\xa6|\xe3Z')