Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement conversion to arbitrary prefixes #17

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions cashaddress/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@ def legacy_address(self):
version_int = Address._address_type('legacy', self.version)[1]
return b58encode_check(Address.code_list_to_string([version_int] + self.payload))

def cash_address(self):
def cash_address(self, prefix=None):
prefix = prefix if prefix is not None else self.prefix
self._check_case(prefix)
is_uppercase = prefix == prefix.upper()
version_int = Address._address_type('cash', self.version)[1]
payload = [version_int] + self.payload
payload = convertbits(payload, 8, 5)
checksum = calculate_checksum(self.prefix, payload)
return self.prefix + ':' + b32encode(payload + checksum)
checksum = calculate_checksum(prefix, payload)
address_string = prefix + ':' + b32encode(payload + checksum)
if is_uppercase:
return address_string.upper()
return address_string

@staticmethod
def code_list_to_string(code_list):
Expand Down Expand Up @@ -94,8 +100,7 @@ def _legacy_string(address_string):

@staticmethod
def _cash_string(address_string):
if address_string.upper() != address_string and address_string.lower() != address_string:
raise InvalidAddress('Cash address contains uppercase and lowercase characters')
Address._check_case(address_string)
address_string = address_string.lower()
colon_count = address_string.count(':')
if colon_count == 0:
Expand All @@ -113,6 +118,11 @@ def _cash_string(address_string):
payload = converted[1:-6]
return Address(version, payload, prefix)

@staticmethod
def _check_case(text):
if text.upper() != text and text.lower() != text:
raise InvalidAddress('Cash address contains uppercase and lowercase characters')


def to_cash_address(address):
return Address.from_string(address).cash_address()
Expand Down
38 changes: 38 additions & 0 deletions tests/test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest

from cashaddress import convert
from cashaddress.convert import Address, InvalidAddress


class TestConversion(unittest.TestCase):
Expand Down Expand Up @@ -61,5 +62,42 @@ def test_is_valid(self):
self.assertFalse(convert.is_valid(False))
self.assertFalse(convert.is_valid('Hello World!'))

def test_prefixes(self):
"""Test a few identical addresses with different CashAddr prefixes"""
legacy_address = "1NLcNpAaBBMekgBZk7NxwdxwtSUTfTV8Aq"
addr = Address.from_string(legacy_address)
default_prefix = addr.prefix
self.assertEqual(default_prefix, Address.MAINNET_PREFIX)
self.assertEqual(addr.cash_address(),
'bitcoincash:qr4pqy6q4cy2d50zpaek57nnrja7289fkskz6jm7yf')
self.assertEqual(addr.cash_address(prefix='abc'),
'abc:qr4pqy6q4cy2d50zpaek57nnrja7289fksqt4c50w9')
self.assertEqual(addr.cash_address(prefix='simpleledger'),
'simpleledger:qr4pqy6q4cy2d50zpaek57nnrja7289fks6e3fw76h')

regtest_address = 'regtest:qr4pqy6q4cy2d50zpaek57nnrja7289fksjm6es9se'
addr2 = Address.from_string(regtest_address)
self.assertEqual(addr2.legacy_address(), legacy_address)
# The prefix defaults to the one in the input string.
self.assertEqual(addr2.prefix, 'regtest')
self.assertEqual(addr2.cash_address(), regtest_address)

def test_prefix_case(self):
with self.assertRaises(InvalidAddress):
Address.from_string(
'rEgTeSt:qr4pqy6q4cy2d50zpaek57nnrja7289fksjm6es9se')
with self.assertRaises(InvalidAddress):
Address.from_string(
'regtest:QR4PQY6Q4CY2D50ZPAEK57NNRJA7289FKSJM6ES9SE')

addr = Address.from_string('regtest:qr4pqy6q4cy2d50zpaek57nnrja7289fksjm6es9se')
# The address should take the same case as the specified prefix
self.assertEqual(addr.cash_address(prefix="SLP"),
'SLP:QR4PQY6Q4CY2D50ZPAEK57NNRJA7289FKSWF89PY2G')
# Do not allow mixed-case prefixes
with self.assertRaises(InvalidAddress):
addr.cash_address(prefix="sLp")


if __name__ == '__main__':
unittest.main()