From 905fb1e6547567964b2ddf2ad0a69c33e976d99a Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Tue, 19 Sep 2023 22:08:31 +0800 Subject: [PATCH 01/10] [explorer/rest]: add mosaic endpoint --- explorer/rest/rest/__init__.py | 7 +++ explorer/rest/rest/db/NemDatabase.py | 64 ++++++++++++++++++++- explorer/rest/rest/facade/NemRestFacade.py | 7 +++ explorer/rest/rest/model/Mosaic.py | 66 ++++++++++++++++++++++ 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 explorer/rest/rest/model/Mosaic.py diff --git a/explorer/rest/rest/__init__.py b/explorer/rest/rest/__init__.py index ef2071032..eb47263f7 100644 --- a/explorer/rest/rest/__init__.py +++ b/explorer/rest/rest/__init__.py @@ -102,6 +102,13 @@ def api_get_nem_namespaces(): return jsonify(nem_api_facade.get_namespaces(limit=limit, offset=offset, sort=sort)) + @app.route('/api/nem/mosaic/') + def api_get_nem_mosaic_by_name(name): + result = nem_api_facade.get_mosaic(name) + if not result: + abort(404) + return jsonify(result) + def setup_error_handlers(app): @app.errorhandler(404) diff --git a/explorer/rest/rest/db/NemDatabase.py b/explorer/rest/rest/db/NemDatabase.py index 6dec7bf21..f45a66121 100644 --- a/explorer/rest/rest/db/NemDatabase.py +++ b/explorer/rest/rest/db/NemDatabase.py @@ -1,10 +1,11 @@ from binascii import hexlify from symbolchain.CryptoTypes import PublicKey -from symbolchain.nem.Network import Network +from symbolchain.nem.Network import Address, Network from symbolchain.Network import NetworkLocator from rest.model.Block import BlockView +from rest.model.Mosaic import MosaicView from rest.model.Namespace import NamespaceView from .DatabaseConnection import DatabaseConnectionPool @@ -18,6 +19,10 @@ def _format_xem_relative(amount): return amount / (10 ** 6) +def _format_relative(amount, divisibility): + return amount / (10 ** divisibility) + + class NemDatabase(DatabaseConnectionPool): """Database containing Nem blockchain data.""" @@ -112,6 +117,31 @@ def _create_namespace_view(self, result): mosaics=mosaics ) + def _create_mosaic_view(self, result): + levy_types = { + 1: 'absolute fee', + 2: 'percentile' + } + + creator_public_key = PublicKey(_format_bytes(result[2])) + levy_type = levy_types.get(result[8], None) + levy_fee = _format_relative(result[11], result[10]) if levy_type else None + + return MosaicView( + namespace_name=result[0], + description=result[1], + creator=self.network.public_key_to_address(creator_public_key), + registered_height=result[3], + initial_supply=result[4], + divisibility=result[5], + supply_mutable=result[6], + transferable=result[7], + levy_type=levy_type, + levy_namespace=result[9], + levy_fee=levy_fee, + levy_recipient=Address(result[12]) if result[12] else None + ) + def get_block(self, height): """Gets block by height in database.""" @@ -173,3 +203,35 @@ def get_namespaces(self, limit, offset, sort): results = cursor.fetchall() return [self._create_namespace_view(result) for result in results] + + def get_mosaic(self, namespace_name): + """Gets mosaic by namespace name in database.""" + + with self.connection() as connection: + cursor = connection.cursor() + cursor.execute(''' + SELECT + m1.namespace_name, + m1.description, + m1.creator, + m1.registered_height, + m1.initial_supply, + m1.divisibility, + m1.supply_mutable, + m1.transferable, + m1.levy_type, + m1.levy_namespace_name, + CASE + WHEN m1.levy_namespace_name = 'nem.xem' THEN 6 + WHEN m1.levy_namespace_name IS NULL THEN NULL + ELSE m2.divisibility + END AS levy_namespace_divisibility, + m1.levy_fee, + m1.levy_recipient + FROM mosaics m1 + LEFT JOIN mosaics m2 ON m1.levy_namespace_name = m2.namespace_name AND m1.levy_namespace_name IS NOT NULL + WHERE m1.namespace_name = %s + ''', (namespace_name,)) + result = cursor.fetchone() + + return self._create_mosaic_view(result) if result else None diff --git a/explorer/rest/rest/facade/NemRestFacade.py b/explorer/rest/rest/facade/NemRestFacade.py index 085e26a77..ce93ee168 100644 --- a/explorer/rest/rest/facade/NemRestFacade.py +++ b/explorer/rest/rest/facade/NemRestFacade.py @@ -36,3 +36,10 @@ def get_namespaces(self, limit, offset, sort): namespaces = self.nem_db.get_namespaces(limit, offset, sort) return [namespace.to_dict() for namespace in namespaces] + + def get_mosaic(self, name): + """Gets mosaic by namespace name.""" + + mosaic = self.nem_db.get_mosaic(name) + + return mosaic.to_dict() if mosaic else None diff --git a/explorer/rest/rest/model/Mosaic.py b/explorer/rest/rest/model/Mosaic.py new file mode 100644 index 000000000..7a9dfc699 --- /dev/null +++ b/explorer/rest/rest/model/Mosaic.py @@ -0,0 +1,66 @@ +class MosaicView: # pylint: disable=too-many-instance-attributes + def __init__( + self, + namespace_name, + description, + creator, + registered_height, + initial_supply, + divisibility, + supply_mutable, + transferable, + levy_type, + levy_namespace, + levy_fee, + levy_recipient + ): + """Create mosaic view.""" + + # pylint: disable=too-many-arguments + + self.namespace_name = namespace_name + self.description = description + self.creator = creator + self.registered_height = registered_height + self.initial_supply = initial_supply + self.divisibility = divisibility + self.supply_mutable = supply_mutable + self.transferable = transferable + self.levy_type = levy_type + self.levy_namespace = levy_namespace + self.levy_fee = levy_fee + self.levy_recipient = levy_recipient + + def __eq__(self, other): + return isinstance(other, MosaicView) and all([ + self.namespace_name == other.namespace_name, + self.description == other.description, + self.creator == other.creator, + self.registered_height == other.registered_height, + self.initial_supply == other.initial_supply, + self.divisibility == other.divisibility, + self.supply_mutable == other.supply_mutable, + self.transferable == other.transferable, + self.levy_type == other.levy_type, + self.levy_namespace == other.levy_namespace, + self.levy_fee == other.levy_fee, + self.levy_recipient == other.levy_recipient + ]) + + def to_dict(self): + """Formats the mosaic info as a dictionary.""" + + return { + 'namespaceName': self.namespace_name, + 'description': self.description, + 'creator': str(self.creator), + 'registeredHeight': self.registered_height, + 'initialSupply': self.initial_supply, + 'divisibility': self.divisibility, + 'supplyMutable': self.supply_mutable, + 'transferable': self.transferable, + 'levyType': self.levy_type, + 'levyNamespace': self.levy_namespace, + 'levyFee': self.levy_fee, + 'levyRecipient': str(self.levy_recipient) if self.levy_recipient else None + } From 1ca00842e59cb5311ce005944b7f65dc2273e577 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Fri, 22 Sep 2023 04:34:09 +0800 Subject: [PATCH 02/10] [explorer/rest]: enhancement on mosaic endpoint, added mosaic name, total_supply, root namespace related info --- explorer/rest/rest/db/NemDatabase.py | 38 ++++++++++++++++++++-------- explorer/rest/rest/model/Mosaic.py | 28 +++++++++++++++++--- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/explorer/rest/rest/db/NemDatabase.py b/explorer/rest/rest/db/NemDatabase.py index f45a66121..5bce938bf 100644 --- a/explorer/rest/rest/db/NemDatabase.py +++ b/explorer/rest/rest/db/NemDatabase.py @@ -124,22 +124,31 @@ def _create_mosaic_view(self, result): } creator_public_key = PublicKey(_format_bytes(result[2])) - levy_type = levy_types.get(result[8], None) - levy_fee = _format_relative(result[11], result[10]) if levy_type else None + levy_type = levy_types.get(result[9], None) + levy_fee = _format_relative(result[12], result[11]) if levy_type else None + + namespace_mosaic_name = result[0].split('.') + namespace_name = '.'.join(namespace_mosaic_name[:-1]) + mosaic_name = namespace_mosaic_name[-1] return MosaicView( - namespace_name=result[0], + mosaic_name=mosaic_name, + namespace_name=namespace_name, description=result[1], creator=self.network.public_key_to_address(creator_public_key), registered_height=result[3], initial_supply=result[4], - divisibility=result[5], - supply_mutable=result[6], - transferable=result[7], + total_supply=result[5], + divisibility=result[6], + supply_mutable=result[7], + transferable=result[8], levy_type=levy_type, - levy_namespace=result[9], + levy_namespace=result[11], levy_fee=levy_fee, - levy_recipient=Address(result[12]) if result[12] else None + levy_recipient=Address(result[13]) if result[13] else None, + root_namespace_registered_height=result[14], + root_namespace_registered_timestamp=result[15], + root_namespace_expiration_height=result[16], ) def get_block(self, height): @@ -216,6 +225,7 @@ def get_mosaic(self, namespace_name): m1.creator, m1.registered_height, m1.initial_supply, + m1.total_supply, m1.divisibility, m1.supply_mutable, m1.transferable, @@ -227,9 +237,17 @@ def get_mosaic(self, namespace_name): ELSE m2.divisibility END AS levy_namespace_divisibility, m1.levy_fee, - m1.levy_recipient + m1.levy_recipient, + n.registered_height AS registered_height, + b.timestamp as registered_height_timestamp, + n.expiration_height FROM mosaics m1 - LEFT JOIN mosaics m2 ON m1.levy_namespace_name = m2.namespace_name AND m1.levy_namespace_name IS NOT NULL + LEFT JOIN mosaics m2 + ON m1.levy_namespace_name = m2.namespace_name AND m1.levy_namespace_name IS NOT NULL + LEFT JOIN namespaces n + ON m1.root_namespace = n.root_namespace + LEFT JOIN blocks b + ON b.height = n.registered_height WHERE m1.namespace_name = %s ''', (namespace_name,)) result = cursor.fetchone() diff --git a/explorer/rest/rest/model/Mosaic.py b/explorer/rest/rest/model/Mosaic.py index 7a9dfc699..0bf6b9284 100644 --- a/explorer/rest/rest/model/Mosaic.py +++ b/explorer/rest/rest/model/Mosaic.py @@ -1,28 +1,35 @@ -class MosaicView: # pylint: disable=too-many-instance-attributes +class MosaicView: # pylint: disable=too-many-instance-attributes, too-many-locals def __init__( self, + mosaic_name, namespace_name, description, creator, registered_height, initial_supply, + total_supply, divisibility, supply_mutable, transferable, levy_type, levy_namespace, levy_fee, - levy_recipient + levy_recipient, + root_namespace_registered_height, + root_namespace_registered_timestamp, + root_namespace_expiration_height, ): """Create mosaic view.""" # pylint: disable=too-many-arguments + self.mosaic_name = mosaic_name self.namespace_name = namespace_name self.description = description self.creator = creator self.registered_height = registered_height self.initial_supply = initial_supply + self.total_supply = total_supply self.divisibility = divisibility self.supply_mutable = supply_mutable self.transferable = transferable @@ -30,37 +37,50 @@ def __init__( self.levy_namespace = levy_namespace self.levy_fee = levy_fee self.levy_recipient = levy_recipient + self.root_namespace_registered_height = root_namespace_registered_height + self.root_namespace_registered_timestamp = root_namespace_registered_timestamp + self.root_namespace_expiration_height = root_namespace_expiration_height def __eq__(self, other): return isinstance(other, MosaicView) and all([ + self.mosaic_name == other.mosaic_name, self.namespace_name == other.namespace_name, self.description == other.description, self.creator == other.creator, self.registered_height == other.registered_height, self.initial_supply == other.initial_supply, + self.total_supply == other.total_supply, self.divisibility == other.divisibility, self.supply_mutable == other.supply_mutable, self.transferable == other.transferable, self.levy_type == other.levy_type, self.levy_namespace == other.levy_namespace, self.levy_fee == other.levy_fee, - self.levy_recipient == other.levy_recipient + self.levy_recipient == other.levy_recipient, + self.root_namespace_registered_height == other.root_namespace_registered_height, + self.root_namespace_registered_timestamp == other.root_namespace_registered_timestamp, + self.root_namespace_expiration_height == other.root_namespace_expiration_height ]) def to_dict(self): """Formats the mosaic info as a dictionary.""" return { + 'mosaicName': self.mosaic_name, 'namespaceName': self.namespace_name, 'description': self.description, 'creator': str(self.creator), 'registeredHeight': self.registered_height, 'initialSupply': self.initial_supply, + 'totalSupply': self.total_supply, 'divisibility': self.divisibility, 'supplyMutable': self.supply_mutable, 'transferable': self.transferable, 'levyType': self.levy_type, 'levyNamespace': self.levy_namespace, 'levyFee': self.levy_fee, - 'levyRecipient': str(self.levy_recipient) if self.levy_recipient else None + 'levyRecipient': str(self.levy_recipient) if self.levy_recipient else None, + 'rootNamespaceRegisteredHeight': self.root_namespace_registered_height, + 'rootNamespaceRegisteredTimestamp': self.root_namespace_registered_timestamp, + 'rootNamespaceExpirationHeight': self.root_namespace_expiration_height } From 826bf4b0ae842cf46ec6af27c59660be37aa2af0 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Fri, 22 Sep 2023 22:45:13 +0800 Subject: [PATCH 03/10] [explorer/rest]: added mosaic registered timestamp --- explorer/rest/rest/db/NemDatabase.py | 38 +++++++++++++++------------- explorer/rest/rest/model/Mosaic.py | 4 +++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/explorer/rest/rest/db/NemDatabase.py b/explorer/rest/rest/db/NemDatabase.py index 5bce938bf..359ef4c8c 100644 --- a/explorer/rest/rest/db/NemDatabase.py +++ b/explorer/rest/rest/db/NemDatabase.py @@ -124,8 +124,8 @@ def _create_mosaic_view(self, result): } creator_public_key = PublicKey(_format_bytes(result[2])) - levy_type = levy_types.get(result[9], None) - levy_fee = _format_relative(result[12], result[11]) if levy_type else None + levy_type = levy_types.get(result[10], None) + levy_fee = _format_relative(result[13], result[12]) if levy_type else None namespace_mosaic_name = result[0].split('.') namespace_name = '.'.join(namespace_mosaic_name[:-1]) @@ -137,18 +137,19 @@ def _create_mosaic_view(self, result): description=result[1], creator=self.network.public_key_to_address(creator_public_key), registered_height=result[3], - initial_supply=result[4], - total_supply=result[5], - divisibility=result[6], - supply_mutable=result[7], - transferable=result[8], + registered_timestamp=result[4], + initial_supply=result[5], + total_supply=result[6], + divisibility=result[7], + supply_mutable=result[8], + transferable=result[9], levy_type=levy_type, - levy_namespace=result[11], + levy_namespace=result[12], levy_fee=levy_fee, - levy_recipient=Address(result[13]) if result[13] else None, - root_namespace_registered_height=result[14], - root_namespace_registered_timestamp=result[15], - root_namespace_expiration_height=result[16], + levy_recipient=Address(result[14]) if result[14] else None, + root_namespace_registered_height=result[15], + root_namespace_registered_timestamp=result[16], + root_namespace_expiration_height=result[17], ) def get_block(self, height): @@ -223,7 +224,8 @@ def get_mosaic(self, namespace_name): m1.namespace_name, m1.description, m1.creator, - m1.registered_height, + m1.registered_height as mosaic_registered_height, + b2.timestamp as mosaic_registered_timestamp, m1.initial_supply, m1.total_supply, m1.divisibility, @@ -238,16 +240,18 @@ def get_mosaic(self, namespace_name): END AS levy_namespace_divisibility, m1.levy_fee, m1.levy_recipient, - n.registered_height AS registered_height, - b.timestamp as registered_height_timestamp, + n.registered_height AS root_namespace_registered_height, + b1.timestamp AS root_namespace_registered_timestamp, n.expiration_height FROM mosaics m1 LEFT JOIN mosaics m2 ON m1.levy_namespace_name = m2.namespace_name AND m1.levy_namespace_name IS NOT NULL LEFT JOIN namespaces n ON m1.root_namespace = n.root_namespace - LEFT JOIN blocks b - ON b.height = n.registered_height + LEFT JOIN blocks b1 + ON b1.height = n.registered_height + LEFT JOIN blocks b2 + ON b2.height = m1.registered_height WHERE m1.namespace_name = %s ''', (namespace_name,)) result = cursor.fetchone() diff --git a/explorer/rest/rest/model/Mosaic.py b/explorer/rest/rest/model/Mosaic.py index 0bf6b9284..48a785f41 100644 --- a/explorer/rest/rest/model/Mosaic.py +++ b/explorer/rest/rest/model/Mosaic.py @@ -6,6 +6,7 @@ def __init__( description, creator, registered_height, + registered_timestamp, initial_supply, total_supply, divisibility, @@ -28,6 +29,7 @@ def __init__( self.description = description self.creator = creator self.registered_height = registered_height + self.registered_timestamp = registered_timestamp self.initial_supply = initial_supply self.total_supply = total_supply self.divisibility = divisibility @@ -48,6 +50,7 @@ def __eq__(self, other): self.description == other.description, self.creator == other.creator, self.registered_height == other.registered_height, + self.registered_timestamp == other.registered_timestamp, self.initial_supply == other.initial_supply, self.total_supply == other.total_supply, self.divisibility == other.divisibility, @@ -71,6 +74,7 @@ def to_dict(self): 'description': self.description, 'creator': str(self.creator), 'registeredHeight': self.registered_height, + 'registeredTimestamp': self.registered_timestamp, 'initialSupply': self.initial_supply, 'totalSupply': self.total_supply, 'divisibility': self.divisibility, From 20cc56ca6564b53bc4e922fada5ec4cc270c7ad7 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Tue, 14 Nov 2023 23:15:22 +0800 Subject: [PATCH 04/10] [explorer/rest]: added mosaic model unit test --- explorer/rest/tests/model/test_Mosaic.py | 115 +++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 explorer/rest/tests/model/test_Mosaic.py diff --git a/explorer/rest/tests/model/test_Mosaic.py b/explorer/rest/tests/model/test_Mosaic.py new file mode 100644 index 000000000..4bc4cf9e3 --- /dev/null +++ b/explorer/rest/tests/model/test_Mosaic.py @@ -0,0 +1,115 @@ +import unittest + +from symbolchain.nem.Network import Address + +from rest.model.Mosaic import MosaicView + + +class MosaicTest(unittest.TestCase): + @staticmethod + def _create_default_mosaic_view(override=None): + mosaic_view = MosaicView( + 'dragonfly', + 'dragon', + 'sample information', + Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), + 2, + '2015-03-29 20:34:19', + 100, + 100, + 0, + False, + True, + 'percentile', + 'nem.xem', + 150000, + Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), + 2, + '2015-03-29 20:34:19', + 525602 + ) + + if override: + setattr(mosaic_view, override[0], override[1]) + + return mosaic_view + + def test_can_create_mosaic_view(self): + # Act: + mosaic_view = self._create_default_mosaic_view() + + # Assert: + self.assertEqual('dragonfly', mosaic_view.mosaic_name) + self.assertEqual('dragon', mosaic_view.namespace_name) + self.assertEqual('sample information', mosaic_view.description) + self.assertEqual(Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), mosaic_view.creator) + self.assertEqual(2, mosaic_view.registered_height) + self.assertEqual('2015-03-29 20:34:19', mosaic_view.registered_timestamp) + self.assertEqual(100, mosaic_view.initial_supply) + self.assertEqual(100, mosaic_view.total_supply) + self.assertEqual(0, mosaic_view.divisibility) + self.assertEqual(False, mosaic_view.supply_mutable) + self.assertEqual(True, mosaic_view.transferable) + self.assertEqual('percentile', mosaic_view.levy_type) + self.assertEqual('nem.xem', mosaic_view.levy_namespace) + self.assertEqual(150000, mosaic_view.levy_fee) + self.assertEqual(Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), mosaic_view.levy_recipient) + self.assertEqual(2, mosaic_view.root_namespace_registered_height) + self.assertEqual('2015-03-29 20:34:19', mosaic_view.root_namespace_registered_timestamp) + self.assertEqual(525602, mosaic_view.root_namespace_expiration_height) + + def test_can_convert_to_simple_dict(self): + # Arrange: + mosaic_view = self._create_default_mosaic_view() + + # Act: + mosaic_view_dict = mosaic_view.to_dict() + + # Assert: + self.assertEqual({ + 'mosaicName': 'dragonfly', + 'namespaceName': 'dragon', + 'description': 'sample information', + 'creator': 'NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3', + 'registeredHeight': 2, + 'registeredTimestamp': '2015-03-29 20:34:19', + 'initialSupply': 100, + 'totalSupply': 100, + 'divisibility': 0, + 'supplyMutable': False, + 'transferable': True, + 'levyType': 'percentile', + 'levyNamespace': 'nem.xem', + 'levyFee': 150000, + 'levyRecipient': 'NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3', + 'rootNamespaceRegisteredHeight': 2, + 'rootNamespaceRegisteredTimestamp': '2015-03-29 20:34:19', + 'rootNamespaceExpirationHeight': 525602 + }, mosaic_view_dict) + + def test_eq_is_supported(self): + # Arrange: + mosaic_view = self._create_default_mosaic_view() + + # Assert: + self.assertEqual(mosaic_view, self._create_default_mosaic_view()) + self.assertNotEqual(mosaic_view, None) + self.assertNotEqual(mosaic_view, 'mosaic_view') + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('mosaic_name', 'xem'))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('namespace_name', 'nem'))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('description', 'no description'))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('creator', 'random creator'))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('registered_height', 10))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('registered_timestamp', 'random timestamp'))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('initial_supply', 99))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('total_supply', 99))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('divisibility', 6))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('supply_mutable', True))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('transferable', False))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('levy_type', None))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('levy_namespace', None))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('levy_fee', None))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('levy_recipient', None))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('root_namespace_registered_height', 4))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('root_namespace_registered_timestamp', 'random timestamp'))) + self.assertNotEqual(mosaic_view, self._create_default_mosaic_view(('root_namespace_expiration_height', 10))) From 3e3217afbad2971820a30928a285a1115f6c0190 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Wed, 15 Nov 2023 03:27:00 +0800 Subject: [PATCH 05/10] [explorer/rest]: adjust data in mosaic model unit test --- explorer/rest/tests/model/test_Mosaic.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/explorer/rest/tests/model/test_Mosaic.py b/explorer/rest/tests/model/test_Mosaic.py index 4bc4cf9e3..69bcfb007 100644 --- a/explorer/rest/tests/model/test_Mosaic.py +++ b/explorer/rest/tests/model/test_Mosaic.py @@ -16,13 +16,13 @@ def _create_default_mosaic_view(override=None): 2, '2015-03-29 20:34:19', 100, - 100, + 1000, 0, False, True, 'percentile', 'nem.xem', - 150000, + 15, Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), 2, '2015-03-29 20:34:19', @@ -46,13 +46,13 @@ def test_can_create_mosaic_view(self): self.assertEqual(2, mosaic_view.registered_height) self.assertEqual('2015-03-29 20:34:19', mosaic_view.registered_timestamp) self.assertEqual(100, mosaic_view.initial_supply) - self.assertEqual(100, mosaic_view.total_supply) + self.assertEqual(1000, mosaic_view.total_supply) self.assertEqual(0, mosaic_view.divisibility) self.assertEqual(False, mosaic_view.supply_mutable) self.assertEqual(True, mosaic_view.transferable) self.assertEqual('percentile', mosaic_view.levy_type) self.assertEqual('nem.xem', mosaic_view.levy_namespace) - self.assertEqual(150000, mosaic_view.levy_fee) + self.assertEqual(15, mosaic_view.levy_fee) self.assertEqual(Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), mosaic_view.levy_recipient) self.assertEqual(2, mosaic_view.root_namespace_registered_height) self.assertEqual('2015-03-29 20:34:19', mosaic_view.root_namespace_registered_timestamp) @@ -74,13 +74,13 @@ def test_can_convert_to_simple_dict(self): 'registeredHeight': 2, 'registeredTimestamp': '2015-03-29 20:34:19', 'initialSupply': 100, - 'totalSupply': 100, + 'totalSupply': 1000, 'divisibility': 0, 'supplyMutable': False, 'transferable': True, 'levyType': 'percentile', 'levyNamespace': 'nem.xem', - 'levyFee': 150000, + 'levyFee': 15, 'levyRecipient': 'NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3', 'rootNamespaceRegisteredHeight': 2, 'rootNamespaceRegisteredTimestamp': '2015-03-29 20:34:19', From 9a884346a8514089e04355e627dac2abf24343e8 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Wed, 15 Nov 2023 03:29:07 +0800 Subject: [PATCH 06/10] [explorer/rest]: added _format_address_bytes helper method --- explorer/rest/rest/db/NemDatabase.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/explorer/rest/rest/db/NemDatabase.py b/explorer/rest/rest/db/NemDatabase.py index 359ef4c8c..2763707e6 100644 --- a/explorer/rest/rest/db/NemDatabase.py +++ b/explorer/rest/rest/db/NemDatabase.py @@ -1,4 +1,4 @@ -from binascii import hexlify +from binascii import hexlify, unhexlify from symbolchain.CryptoTypes import PublicKey from symbolchain.nem.Network import Address, Network @@ -11,6 +11,10 @@ from .DatabaseConnection import DatabaseConnectionPool +def _format_address_bytes(buffer): + return unhexlify(_format_bytes(buffer)) + + def _format_bytes(buffer): return hexlify(buffer).decode('utf8').upper() @@ -146,7 +150,7 @@ def _create_mosaic_view(self, result): levy_type=levy_type, levy_namespace=result[12], levy_fee=levy_fee, - levy_recipient=Address(result[14]) if result[14] else None, + levy_recipient=Address(_format_address_bytes(result[14])) if result[14] else None, root_namespace_registered_height=result[15], root_namespace_registered_timestamp=result[16], root_namespace_expiration_height=result[17], From 1e7e1a9fa23600f7dcf9ef0d3f589bccfa1142d5 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Wed, 15 Nov 2023 03:30:11 +0800 Subject: [PATCH 07/10] [explorer/rest]: convert timestamp into string format --- explorer/rest/rest/db/NemDatabase.py | 6 +++--- explorer/rest/rest/model/Mosaic.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/explorer/rest/rest/db/NemDatabase.py b/explorer/rest/rest/db/NemDatabase.py index 2763707e6..874ae32ff 100644 --- a/explorer/rest/rest/db/NemDatabase.py +++ b/explorer/rest/rest/db/NemDatabase.py @@ -141,18 +141,18 @@ def _create_mosaic_view(self, result): description=result[1], creator=self.network.public_key_to_address(creator_public_key), registered_height=result[3], - registered_timestamp=result[4], + registered_timestamp=str(result[4]), initial_supply=result[5], total_supply=result[6], divisibility=result[7], supply_mutable=result[8], transferable=result[9], levy_type=levy_type, - levy_namespace=result[12], + levy_namespace=result[11], levy_fee=levy_fee, levy_recipient=Address(_format_address_bytes(result[14])) if result[14] else None, root_namespace_registered_height=result[15], - root_namespace_registered_timestamp=result[16], + root_namespace_registered_timestamp=str(result[16]), root_namespace_expiration_height=result[17], ) diff --git a/explorer/rest/rest/model/Mosaic.py b/explorer/rest/rest/model/Mosaic.py index 48a785f41..9d4d3d1aa 100644 --- a/explorer/rest/rest/model/Mosaic.py +++ b/explorer/rest/rest/model/Mosaic.py @@ -74,7 +74,7 @@ def to_dict(self): 'description': self.description, 'creator': str(self.creator), 'registeredHeight': self.registered_height, - 'registeredTimestamp': self.registered_timestamp, + 'registeredTimestamp': str(self.registered_timestamp), 'initialSupply': self.initial_supply, 'totalSupply': self.total_supply, 'divisibility': self.divisibility, @@ -85,6 +85,6 @@ def to_dict(self): 'levyFee': self.levy_fee, 'levyRecipient': str(self.levy_recipient) if self.levy_recipient else None, 'rootNamespaceRegisteredHeight': self.root_namespace_registered_height, - 'rootNamespaceRegisteredTimestamp': self.root_namespace_registered_timestamp, + 'rootNamespaceRegisteredTimestamp': str(self.root_namespace_registered_timestamp), 'rootNamespaceExpirationHeight': self.root_namespace_expiration_height } From 2232b7a0cc459cf207e689e3f704ec1e904755b5 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Wed, 15 Nov 2023 03:51:02 +0800 Subject: [PATCH 08/10] [explorer/rest]: added mosaic view data in test utils --- explorer/rest/tests/test/DatabaseTestUtils.py | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/explorer/rest/tests/test/DatabaseTestUtils.py b/explorer/rest/tests/test/DatabaseTestUtils.py index 6a7b7fd19..c29807b13 100644 --- a/explorer/rest/tests/test/DatabaseTestUtils.py +++ b/explorer/rest/tests/test/DatabaseTestUtils.py @@ -7,6 +7,7 @@ from rest.db.NemDatabase import NemDatabase from rest.model.Block import BlockView +from rest.model.Mosaic import MosaicView from rest.model.Namespace import NamespaceView Block = namedtuple( @@ -52,6 +53,7 @@ 'levy_recipient' ] ) + DatabaseConfig = namedtuple('DatabaseConfig', ['database', 'user', 'password', 'host', 'port']) # region test data @@ -110,10 +112,10 @@ 0, False, True, - None, - None, - None, - None + 2, + 'nem.xem', + 15000, + 'NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3' ) ] @@ -147,7 +149,30 @@ 'registeredHeight': 2, 'registeredTimestamp': '2015-03-29 20:34:19' }] - ), + ) +] + +MOSAIC_VIEWS = [ + MosaicView( + 'dragonfly', + 'dragon', + MOSAICS[0].description, + Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), + MOSAICS[0].registered_height, + '2015-03-29 20:34:19', + MOSAICS[0].initial_supply, + MOSAICS[0].total_supply, + MOSAICS[0].divisibility, + MOSAICS[0].supply_mutable, + MOSAICS[0].transferable, + 'percentile', + 'nem.xem', + 0.015, + Address('NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3'), + 2, + '2015-03-29 20:34:19', + 525602 + ) ] # endregion From 60a24d330e02bd04ba616be7cf7b97d16eefc08d Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Wed, 15 Nov 2023 03:52:10 +0800 Subject: [PATCH 09/10] [explorer/rest]: added more unit test for search mosaic --- explorer/rest/tests/db/test_NemDatabase.py | 26 +++++++++++++++--- .../rest/tests/facade/test_NemRestFacade.py | 24 ++++++++++++++++- explorer/rest/tests/test_rest.py | 27 ++++++++++++++++++- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/explorer/rest/tests/db/test_NemDatabase.py b/explorer/rest/tests/db/test_NemDatabase.py index e313d949e..0e68b8d84 100644 --- a/explorer/rest/tests/db/test_NemDatabase.py +++ b/explorer/rest/tests/db/test_NemDatabase.py @@ -2,7 +2,7 @@ from rest.db.NemDatabase import NemDatabase -from ..test.DatabaseTestUtils import BLOCK_VIEWS, NAMESPACE_VIEWS, DatabaseTestBase +from ..test.DatabaseTestUtils import BLOCK_VIEWS, MOSAIC_VIEWS, NAMESPACE_VIEWS, DatabaseTestBase BlockQueryParams = namedtuple('BlockQueryParams', ['limit', 'offset', 'min_height', 'sort']) PaginationQueryParams = namedtuple('PaginationQueryParams', ['limit', 'offset', 'sort']) @@ -17,6 +17,8 @@ EXPECTED_NAMESPACE_VIEW_2 = NAMESPACE_VIEWS[1] +EXPECTED_MOSAIC_VIEW_1 = MOSAIC_VIEWS[0] + # endregion @@ -79,10 +81,8 @@ def test_can_query_blocks_sorted_by_height_desc(self): # region namespace tests def _assert_can_query_namespace_by_name(self, name, expected_namespace): - # Arrange: nem_db = NemDatabase(self.db_config, self.network_name) - # Act: namespace_view = nem_db.get_namespace(name) # Assert: @@ -123,3 +123,23 @@ def test_can_query_namespaces_sorted_by_id_desc(self): ) # endregion + + # region mosaic tests + + def _assert_can_query_mosaic_by_name(self, namespace_name, expected_mosaic): + # Arrange: + nem_db = NemDatabase(self.db_config, self.network_name) + + # Act: + mosaic_view = nem_db.get_mosaic(namespace_name) + + # Assert: + self.assertEqual(expected_mosaic, mosaic_view) + + def test_can_query_mosaic_by_name(self): + self._assert_can_query_mosaic_by_name('dragon.dragonfly', EXPECTED_MOSAIC_VIEW_1) + + def test_cannot_query_nonexistent_mosaic(self): + self._assert_can_query_mosaic_by_name('non-exist-mosaic', None) + + # endregion diff --git a/explorer/rest/tests/facade/test_NemRestFacade.py b/explorer/rest/tests/facade/test_NemRestFacade.py index 014f35dd3..313d6f1f9 100644 --- a/explorer/rest/tests/facade/test_NemRestFacade.py +++ b/explorer/rest/tests/facade/test_NemRestFacade.py @@ -1,7 +1,7 @@ from rest.facade.NemRestFacade import NemRestFacade from ..db.test_NemDatabase import BlockQueryParams, PaginationQueryParams -from ..test.DatabaseTestUtils import BLOCK_VIEWS, NAMESPACE_VIEWS, DatabaseTestBase +from ..test.DatabaseTestUtils import BLOCK_VIEWS, MOSAIC_VIEWS, NAMESPACE_VIEWS, DatabaseTestBase # region test data @@ -13,6 +13,8 @@ EXPECTED_NAMESPACE_2 = NAMESPACE_VIEWS[1].to_dict() +EXPECTED_MOSAIC_1 = MOSAIC_VIEWS[0].to_dict() + # endregion @@ -107,3 +109,23 @@ def test_namespaces_sorted_by_id_desc(self): self._assert_can_retrieve_namespaces(PaginationQueryParams(10, 0, 'desc'), [EXPECTED_NAMESPACE_2, EXPECTED_NAMESPACE_1]) # endregion + + # region mosaic tests + + def _assert_can_retrieve_mosaic(self, name, expected_mosaic): + # Arrange: + nem_rest_facade = NemRestFacade(self.db_config, self.network_name) + + # Act: + mosaic = nem_rest_facade.get_mosaic(name) + + # Assert: + self.assertEqual(expected_mosaic, mosaic) + + def test_retrieve_mosaic_by_name(self): + self._assert_can_retrieve_mosaic('dragon.dragonfly', EXPECTED_MOSAIC_1) + + def test_returns_none_for_nonexistent_mosaic(self): + self._assert_can_retrieve_mosaic('non_existing_mosaic', None) + + # endregion diff --git a/explorer/rest/tests/test_rest.py b/explorer/rest/tests/test_rest.py index 1c29ed874..70f1ef224 100644 --- a/explorer/rest/tests/test_rest.py +++ b/explorer/rest/tests/test_rest.py @@ -7,7 +7,7 @@ from rest import create_app -from .test.DatabaseTestUtils import BLOCK_VIEWS, NAMESPACE_VIEWS, DatabaseConfig, initialize_database +from .test.DatabaseTestUtils import BLOCK_VIEWS, MOSAIC_VIEWS, NAMESPACE_VIEWS, DatabaseConfig, initialize_database DATABASE_CONFIG_INI = 'db_config.ini' @@ -21,6 +21,7 @@ EXPECTED_NAMESPACE_VIEW_2 = NAMESPACE_VIEWS[1] +EXPECTED_MOSAIC_VIEW_1 = MOSAIC_VIEWS[0] # endregion @@ -290,3 +291,27 @@ def test_api_nem_namespaces_invalid_sort(client): # pylint: disable=redefined-o # endregion + + +# region /mosaic/ + +def _assert_get_api_nem_mosaic_by_name(client, name, expected_status_code, expected_result): # pylint: disable=redefined-outer-name + # Act: + response = client.get(f'/api/nem/mosaic/{name}') + + # Assert: + _assert_status_code_and_headers(response, expected_status_code) + assert expected_result == response.json + + +def test_api_nem_mosaic_by_name(client): # pylint: disable=redefined-outer-name + _assert_get_api_nem_mosaic_by_name(client, 'dragon.dragonfly', 200, EXPECTED_MOSAIC_VIEW_1.to_dict()) + + +def test_api_nem_mosaic_non_exist(client): # pylint: disable=redefined-outer-name + _assert_get_api_nem_mosaic_by_name(client, 'non_exist_mosaic', 404, { + 'message': 'Resource not found', + 'status': 404 + }) + +# endregion From 55997798908689bc88df8ac1be6914fcec9e5be3 Mon Sep 17 00:00:00 2001 From: AnthonyLaw Date: Wed, 15 Nov 2023 04:01:56 +0800 Subject: [PATCH 10/10] [explorer/rest]: fix lint duplicate-cod error --- explorer/rest/tests/db/test_NemDatabase.py | 44 ++++++++-------------- explorer/rest/tests/test_rest.py | 44 ++++++++-------------- 2 files changed, 30 insertions(+), 58 deletions(-) diff --git a/explorer/rest/tests/db/test_NemDatabase.py b/explorer/rest/tests/db/test_NemDatabase.py index 0e68b8d84..dbf3c3543 100644 --- a/explorer/rest/tests/db/test_NemDatabase.py +++ b/explorer/rest/tests/db/test_NemDatabase.py @@ -7,20 +7,6 @@ BlockQueryParams = namedtuple('BlockQueryParams', ['limit', 'offset', 'min_height', 'sort']) PaginationQueryParams = namedtuple('PaginationQueryParams', ['limit', 'offset', 'sort']) -# region test data - -EXPECTED_BLOCK_VIEW_1 = BLOCK_VIEWS[0] - -EXPECTED_BLOCK_VIEW_2 = BLOCK_VIEWS[1] - -EXPECTED_NAMESPACE_VIEW_1 = NAMESPACE_VIEWS[0] - -EXPECTED_NAMESPACE_VIEW_2 = NAMESPACE_VIEWS[1] - -EXPECTED_MOSAIC_VIEW_1 = MOSAIC_VIEWS[0] - -# endregion - class NemDatabaseTest(DatabaseTestBase): @@ -47,34 +33,34 @@ def _assert_can_query_blocks_with_filter(self, query_params, expected_blocks): self.assertEqual(expected_blocks, blocks_view) def test_can_query_block_by_height_1(self): - self._assert_can_query_block_by_height(1, EXPECTED_BLOCK_VIEW_1) + self._assert_can_query_block_by_height(1, BLOCK_VIEWS[0]) def test_cannot_query_nonexistent_block(self): self._assert_can_query_block_by_height(3, None) def test_can_query_blocks_filtered_limit(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(1, 0, 1, 'desc'), [EXPECTED_BLOCK_VIEW_2]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(1, 0, 1, 'desc'), [BLOCK_VIEWS[1]]) def test_can_query_blocks_filtered_offset_0(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(1, 0, 0, 'desc'), [EXPECTED_BLOCK_VIEW_2]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(1, 0, 0, 'desc'), [BLOCK_VIEWS[1]]) def test_can_query_blocks_filtered_offset_1(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(1, 1, 0, 'desc'), [EXPECTED_BLOCK_VIEW_1]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(1, 1, 0, 'desc'), [BLOCK_VIEWS[0]]) def test_can_query_blocks_filtered_min_height_1(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 1, 'desc'), [EXPECTED_BLOCK_VIEW_2, EXPECTED_BLOCK_VIEW_1]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 1, 'desc'), [BLOCK_VIEWS[1], BLOCK_VIEWS[0]]) def test_can_query_blocks_filtered_min_height_2(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 2, 'desc'), [EXPECTED_BLOCK_VIEW_2]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 2, 'desc'), [BLOCK_VIEWS[1]]) def test_can_query_blocks_filtered_min_height_3(self): self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 3, 'desc'), []) def test_can_query_blocks_sorted_by_height_asc(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 0, 'asc'), [EXPECTED_BLOCK_VIEW_1, EXPECTED_BLOCK_VIEW_2]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 0, 'asc'), [BLOCK_VIEWS[0], BLOCK_VIEWS[1]]) def test_can_query_blocks_sorted_by_height_desc(self): - self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 0, 'desc'), [EXPECTED_BLOCK_VIEW_2, EXPECTED_BLOCK_VIEW_1]) + self._assert_can_query_blocks_with_filter(BlockQueryParams(10, 0, 0, 'desc'), [BLOCK_VIEWS[1], BLOCK_VIEWS[0]]) # endregion @@ -99,27 +85,27 @@ def _assert_can_query_namespaces_with_filter(self, query_params, expected_namesp self.assertEqual(expected_namespaces, namespaces_view) def test_can_query_namespace_by_name(self): - self._assert_can_query_namespace_by_name('oxford', EXPECTED_NAMESPACE_VIEW_1) + self._assert_can_query_namespace_by_name('oxford', NAMESPACE_VIEWS[0]) def test_cannot_query_nonexistent_namespace(self): self._assert_can_query_namespace_by_name('non_exist', None) def test_can_query_namespaces_filtered_limit(self): - self._assert_can_query_namespaces_with_filter(PaginationQueryParams(1, 0, 'desc'), [EXPECTED_NAMESPACE_VIEW_2]) + self._assert_can_query_namespaces_with_filter(PaginationQueryParams(1, 0, 'desc'), [NAMESPACE_VIEWS[1]]) def test_can_query_namespaces_filtered_offset_0(self): - self._assert_can_query_namespaces_with_filter(PaginationQueryParams(1, 0, 'desc'), [EXPECTED_NAMESPACE_VIEW_2]) + self._assert_can_query_namespaces_with_filter(PaginationQueryParams(1, 0, 'desc'), [NAMESPACE_VIEWS[1]]) def test_can_query_namespaces_filtered_offset_1(self): - self._assert_can_query_namespaces_with_filter(PaginationQueryParams(1, 1, 'desc'), [EXPECTED_NAMESPACE_VIEW_1]) + self._assert_can_query_namespaces_with_filter(PaginationQueryParams(1, 1, 'desc'), [NAMESPACE_VIEWS[0]]) def test_can_query_namespaces_sorted_by_id_asc(self): - self._assert_can_query_namespaces_with_filter(PaginationQueryParams(10, 0, 'asc'), [EXPECTED_NAMESPACE_VIEW_1, EXPECTED_NAMESPACE_VIEW_2]) + self._assert_can_query_namespaces_with_filter(PaginationQueryParams(10, 0, 'asc'), [NAMESPACE_VIEWS[0], NAMESPACE_VIEWS[1]]) def test_can_query_namespaces_sorted_by_id_desc(self): self._assert_can_query_namespaces_with_filter( PaginationQueryParams(10, 0, 'desc'), - [EXPECTED_NAMESPACE_VIEW_2, EXPECTED_NAMESPACE_VIEW_1] + [NAMESPACE_VIEWS[1], NAMESPACE_VIEWS[0]] ) # endregion @@ -137,7 +123,7 @@ def _assert_can_query_mosaic_by_name(self, namespace_name, expected_mosaic): self.assertEqual(expected_mosaic, mosaic_view) def test_can_query_mosaic_by_name(self): - self._assert_can_query_mosaic_by_name('dragon.dragonfly', EXPECTED_MOSAIC_VIEW_1) + self._assert_can_query_mosaic_by_name('dragon.dragonfly', MOSAIC_VIEWS[0]) def test_cannot_query_nonexistent_mosaic(self): self._assert_can_query_mosaic_by_name('non-exist-mosaic', None) diff --git a/explorer/rest/tests/test_rest.py b/explorer/rest/tests/test_rest.py index 70f1ef224..67f3540d8 100644 --- a/explorer/rest/tests/test_rest.py +++ b/explorer/rest/tests/test_rest.py @@ -11,20 +11,6 @@ DATABASE_CONFIG_INI = 'db_config.ini' -# region test data - -EXPECTED_BLOCK_VIEW_1 = BLOCK_VIEWS[0] - -EXPECTED_BLOCK_VIEW_2 = BLOCK_VIEWS[1] - -EXPECTED_NAMESPACE_VIEW_1 = NAMESPACE_VIEWS[0] - -EXPECTED_NAMESPACE_VIEW_2 = NAMESPACE_VIEWS[1] - -EXPECTED_MOSAIC_VIEW_1 = MOSAIC_VIEWS[0] - -# endregion - # region fixtures @@ -91,7 +77,7 @@ def _assert_get_api_nem_block_by_height(client, height, expected_status_code, ex def test_api_nem_block_by_height(client): # pylint: disable=redefined-outer-name - _assert_get_api_nem_block_by_height(client, 1, 200, EXPECTED_BLOCK_VIEW_1.to_dict()) + _assert_get_api_nem_block_by_height(client, 1, 200, BLOCK_VIEWS[0].to_dict()) def test_api_nem_block_non_exist(client): # pylint: disable=redefined-outer-name @@ -144,15 +130,15 @@ def test_api_nem_blocks_without_params(client): # pylint: disable=redefined-out # Assert: _assert_status_code_and_headers(response, 200) - assert [EXPECTED_BLOCK_VIEW_2.to_dict(), EXPECTED_BLOCK_VIEW_1.to_dict()] == response.json + assert [BLOCK_VIEWS[1].to_dict(), BLOCK_VIEWS[0].to_dict()] == response.json def test_api_nem_blocks_applies_limit(client): # pylint: disable=redefined-outer-name - _assert_get_api_nem_blocks(client, 200, [EXPECTED_BLOCK_VIEW_2.to_dict()], limit=1) + _assert_get_api_nem_blocks(client, 200, [BLOCK_VIEWS[1].to_dict()], limit=1) def test_api_nem_blocks_applies_offset(client): # pylint: disable=redefined-outer-name - _assert_get_api_nem_blocks(client, 200, [EXPECTED_BLOCK_VIEW_1.to_dict()], offset=1) + _assert_get_api_nem_blocks(client, 200, [BLOCK_VIEWS[0].to_dict()], offset=1) def test_api_nem_blocks_applies_min_height(client): # pylint: disable=redefined-outer-name, invalid-name @@ -160,15 +146,15 @@ def test_api_nem_blocks_applies_min_height(client): # pylint: disable=redefined def test_api_nem_blocks_applies_sorted_by_height_desc(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_blocks(client, 200, [EXPECTED_BLOCK_VIEW_2.to_dict(), EXPECTED_BLOCK_VIEW_1.to_dict()], sort='desc') + _assert_get_api_nem_blocks(client, 200, [BLOCK_VIEWS[1].to_dict(), BLOCK_VIEWS[0].to_dict()], sort='desc') def test_api_nem_blocks_applies_sorted_by_height_asc(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_blocks(client, 200, [EXPECTED_BLOCK_VIEW_1.to_dict(), EXPECTED_BLOCK_VIEW_2.to_dict()], sort='asc') + _assert_get_api_nem_blocks(client, 200, [BLOCK_VIEWS[0].to_dict(), BLOCK_VIEWS[1].to_dict()], sort='asc') def test_api_nem_blocks_with_all_params(client): # pylint: disable=redefined-outer-name - _assert_get_api_nem_blocks(client, 200, [EXPECTED_BLOCK_VIEW_2.to_dict()], limit=1, offset=1, min_height=1, sort='asc') + _assert_get_api_nem_blocks(client, 200, [BLOCK_VIEWS[1].to_dict()], limit=1, offset=1, min_height=1, sort='asc') def test_api_nem_blocks_invalid_min_height(client): # pylint: disable=redefined-outer-name, invalid-name @@ -206,7 +192,7 @@ def _assert_get_api_nem_namespace_by_name(client, name, expected_status_code, ex def test_api_nem_namespace_by_name(client): # pylint: disable=redefined-outer-name - _assert_get_api_nem_namespace_by_name(client, 'oxford', 200, EXPECTED_NAMESPACE_VIEW_1.to_dict()) + _assert_get_api_nem_namespace_by_name(client, 'oxford', 200, NAMESPACE_VIEWS[0].to_dict()) def test_api_nem_namespace_non_exist(client): # pylint: disable=redefined-outer-name @@ -240,27 +226,27 @@ def test_api_nem_namespaces_without_params(client): # pylint: disable=redefined # Assert: _assert_status_code_and_headers(response, 200) - assert [EXPECTED_NAMESPACE_VIEW_2.to_dict(), EXPECTED_NAMESPACE_VIEW_1.to_dict()] == response.json + assert [NAMESPACE_VIEWS[1].to_dict(), NAMESPACE_VIEWS[0].to_dict()] == response.json def test_api_nem_namespaces_applies_limit(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_namespaces(client, 200, [EXPECTED_NAMESPACE_VIEW_2.to_dict()], limit=1) + _assert_get_api_nem_namespaces(client, 200, [NAMESPACE_VIEWS[1].to_dict()], limit=1) def test_api_nem_namespaces_applies_offset(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_namespaces(client, 200, [EXPECTED_NAMESPACE_VIEW_1.to_dict()], offset=1) + _assert_get_api_nem_namespaces(client, 200, [NAMESPACE_VIEWS[0].to_dict()], offset=1) def test_api_nem_namespaces_applies_sorted_by_id_desc(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_namespaces(client, 200, [EXPECTED_NAMESPACE_VIEW_2.to_dict(), EXPECTED_NAMESPACE_VIEW_1.to_dict()], sort='desc') + _assert_get_api_nem_namespaces(client, 200, [NAMESPACE_VIEWS[1].to_dict(), NAMESPACE_VIEWS[0].to_dict()], sort='desc') def test_api_nem_namespaces_applies_sorted_by_id_asc(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_namespaces(client, 200, [EXPECTED_NAMESPACE_VIEW_1.to_dict(), EXPECTED_NAMESPACE_VIEW_2.to_dict()], sort='asc') + _assert_get_api_nem_namespaces(client, 200, [NAMESPACE_VIEWS[0].to_dict(), NAMESPACE_VIEWS[1].to_dict()], sort='asc') def test_api_nem_namespaces_with_all_params(client): # pylint: disable=redefined-outer-name, invalid-name - _assert_get_api_nem_namespaces(client, 200, [EXPECTED_NAMESPACE_VIEW_2.to_dict()], limit=1, offset=1, sort='asc') + _assert_get_api_nem_namespaces(client, 200, [NAMESPACE_VIEWS[1].to_dict()], limit=1, offset=1, sort='asc') def _assert_get_api_nem_namespaces_fail(client, expected_status_code, **query_params): # pylint: disable=redefined-outer-name @@ -305,7 +291,7 @@ def _assert_get_api_nem_mosaic_by_name(client, name, expected_status_code, expec def test_api_nem_mosaic_by_name(client): # pylint: disable=redefined-outer-name - _assert_get_api_nem_mosaic_by_name(client, 'dragon.dragonfly', 200, EXPECTED_MOSAIC_VIEW_1.to_dict()) + _assert_get_api_nem_mosaic_by_name(client, 'dragon.dragonfly', 200, MOSAIC_VIEWS[0].to_dict()) def test_api_nem_mosaic_non_exist(client): # pylint: disable=redefined-outer-name