From 11e9881009f52400b0cbaf6144fd055a7b12fcc3 Mon Sep 17 00:00:00 2001 From: William Luke Date: Tue, 16 Nov 2021 16:37:16 +0300 Subject: [PATCH] setup initial testing --- .../cic_eth/server/{__main__.py => app.py} | 13 +- apps/cic-eth/cic_eth/server/celery_helper.py | 61 ++ apps/cic-eth/cic_eth/server/config.py | 9 + .../server/controllers/account_controller.py | 134 +--- .../server/controllers/token_controller.py | 28 +- .../cic-eth/cic_eth/server/models/__init__.py | 1 + .../cic_eth/server/models/base_model_.py | 1 + apps/cic-eth/cic_eth/server/models/token.py | 28 +- .../cic_eth/server/models/token_balance.py | 19 +- .../cic_eth/server/models/transaction.py | 609 ++++++++++++++++++ .../swagger.yaml => openapi/server.yaml} | 20 +- apps/cic-eth/cic_eth/server/test/__init__.py | 16 - .../server/test/test_account_controller.py | 95 --- .../server/test/test_token_controller.py | 29 - apps/cic-eth/setup.cfg | 1 + .../tests/server/test_account_controller.py | 111 ++++ .../tests/server/test_token_controller.py | 43 ++ apps/contract-migration/docker/Dockerfile | 2 +- docker-compose.yml | 3 +- 19 files changed, 912 insertions(+), 311 deletions(-) rename apps/cic-eth/cic_eth/server/{__main__.py => app.py} (62%) create mode 100644 apps/cic-eth/cic_eth/server/celery_helper.py create mode 100644 apps/cic-eth/cic_eth/server/config.py create mode 100644 apps/cic-eth/cic_eth/server/models/transaction.py rename apps/cic-eth/cic_eth/server/{swagger/swagger.yaml => openapi/server.yaml} (95%) delete mode 100644 apps/cic-eth/cic_eth/server/test/__init__.py delete mode 100644 apps/cic-eth/cic_eth/server/test/test_account_controller.py delete mode 100644 apps/cic-eth/cic_eth/server/test/test_token_controller.py create mode 100644 apps/cic-eth/tests/server/test_account_controller.py create mode 100644 apps/cic-eth/tests/server/test_token_controller.py diff --git a/apps/cic-eth/cic_eth/server/__main__.py b/apps/cic-eth/cic_eth/server/app.py similarity index 62% rename from apps/cic-eth/cic_eth/server/__main__.py rename to apps/cic-eth/cic_eth/server/app.py index a88edb31..d7a74df4 100644 --- a/apps/cic-eth/cic_eth/server/__main__.py +++ b/apps/cic-eth/cic_eth/server/app.py @@ -1,21 +1,24 @@ #!/usr/bin/env python3 -from cic_eth.server import encoder import cic_eth.cli import connexion from cic_eth.graphql.config import config +from cic_eth.server import encoder celery_app = cic_eth.cli.CeleryApp.from_config(config) celery_app.set_default() -def main(): - app = connexion.App(__name__, specification_dir='./swagger/') +def create_app(test_config=None): + app = connexion.App(__name__, specification_dir='./openapi/') + if test_config: + app.app.config.update(test_config) app.app.json_encoder = encoder.JSONEncoder - app.add_api('swagger.yaml', arguments={ + app.add_api('server.yaml', arguments={ 'title': 'Grassroots Economics'}, pythonic_params=True) app.run(port=5000) + return app.app if __name__ == '__main__': - main() + create_app() diff --git a/apps/cic-eth/cic_eth/server/celery_helper.py b/apps/cic-eth/cic_eth/server/celery_helper.py new file mode 100644 index 00000000..37a97eb9 --- /dev/null +++ b/apps/cic-eth/cic_eth/server/celery_helper.py @@ -0,0 +1,61 @@ +import json +import logging +import sys +import uuid + +import redis +from cic_eth.api.api_task import Api +from cic_eth.server.config import config + +log = logging.getLogger(__name__) + + +chain_spec = config.get('CHAIN_SPEC') +celery_queue = config.get('CELERY_QUEUE') + +api = Api( + chain_spec, + queue=celery_queue, +) + + +redis_host = config.get('REDIS_HOST') +redis_port = config.get('REDIS_PORT') +redis_db = config.get('REDIS_DB') + + +def call(method, *args): + """ Creates a redis channel and calls `cic_eth.api` with the provided `method` and `*args`. Returns the result of the api call + """ + redis_channel = str(uuid.uuid4()) + r = redis.Redis(redis_host, redis_port, redis_db) + ps = r.pubsub() + ps.subscribe(redis_channel) + api = Api( + chain_spec, + queue=celery_queue, + callback_param='{}:{}:{}:{}'.format( + redis_host, redis_port, redis_db, redis_channel), + callback_task='cic_eth.callbacks.redis.redis', + callback_queue=celery_queue, + ) + log.debug(f"cic_eth.api.{method}({args})") + getattr(api, method)(*args) + ps.get_message() + try: + o = ps.get_message(timeout=config.get('REDIS_TIMEOUT')) + log.debug(f"cic_eth.api.{method}({args})\n {o}") + except TimeoutError as e: + sys.stderr.write( + f'cic_eth.api.{method}({args}) timed out:\n {e}') + sys.exit(1) + + ps.unsubscribe() + try: + result = json.loads(o['data'])["result"] + return result + + except Exception as e: + sys.stderr.write( + f'Unable to parse Data:\n{o}\n Error:\n{e}') + sys.exit(1) diff --git a/apps/cic-eth/cic_eth/server/config.py b/apps/cic-eth/cic_eth/server/config.py new file mode 100644 index 00000000..4cc66f32 --- /dev/null +++ b/apps/cic-eth/cic_eth/server/config.py @@ -0,0 +1,9 @@ +import cic_eth.cli + +arg_flags = cic_eth.cli.argflag_std_base +local_arg_flags = cic_eth.cli.argflag_local_taskcallback +argparser = cic_eth.cli.ArgumentParser(arg_flags) + +argparser.process_local_flags(local_arg_flags) +args = argparser.parse_args() +config = cic_eth.cli.Config.from_args(args, arg_flags, local_arg_flags) \ No newline at end of file diff --git a/apps/cic-eth/cic_eth/server/controllers/account_controller.py b/apps/cic-eth/cic_eth/server/controllers/account_controller.py index 9dc54629..dccce221 100644 --- a/apps/cic-eth/cic_eth/server/controllers/account_controller.py +++ b/apps/cic-eth/cic_eth/server/controllers/account_controller.py @@ -1,76 +1,14 @@ -import json import logging -import sys -import uuid - -import connexion -import redis -import six -from cic_eth.api.api_task import Api -from cic_eth.graphql.config import config -from cic_eth.server import util -from cic_eth.server.models.token import Token # noqa: E501 -from cic_eth.server.models.token_balance import TokenBalance # noqa: E501 +from cic_eth.server.celery_helper import call +from cic_eth.server.models import TokenBalance, Transaction log = logging.getLogger(__name__) -chain_spec = config.get('CHAIN_SPEC') -celery_queue = config.get('CELERY_QUEUE') - -api = Api( - chain_spec, - queue=celery_queue, -) - - -redis_host = config.get('REDIS_HOST') -redis_port = config.get('REDIS_PORT') -redis_db = config.get('REDIS_DB') - - -logging.basicConfig(level=logging.DEBUG) - -log = logging.getLogger(__name__) - - -def call(method, *args): - redis_channel = str(uuid.uuid4()) - r = redis.Redis(redis_host, redis_port, redis_db) - ps = r.pubsub() - ps.subscribe(redis_channel) - log.debug(f"message 1: {ps.get_message()}") # Subscription Object - print(f"Channel init {redis_channel}") - print(args) - api = Api( - chain_spec, - queue=celery_queue, - callback_param='{}:{}:{}:{}'.format( - redis_host, redis_port, redis_db, redis_channel), - callback_task='cic_eth.callbacks.redis.redis', - callback_queue=celery_queue, - ) - getattr(api, method)(*args) - - log.debug(f"message 2: {ps.get_message()}") # returns None !? - try: - o = ps.get_message(timeout=config.get('REDIS_TIMEOUT')) - log.debug(f"message 3: {o}") - - except TimeoutError as e: - sys.stderr.write( - 'got no new address from cic-eth before timeout: {}\n'.format(e)) - sys.exit(1) - ps.unsubscribe() - print(o) - m = json.loads(o['data']) - return m["result"] - - -def account_balance(address, token_symbol, include_pending=True): # noqa: E501 +def account_balance(address, token_symbol, include_pending=True): """account_balance - Retrieve Address Balance # noqa: E501 + Retrieve Address Balance :param address: :type address: dict | bytes @@ -81,34 +19,33 @@ def account_balance(address, token_symbol, include_pending=True): # noqa: E501 :rtype: TokenBalance """ - task = api.balance(address=address, token_symbol=token_symbol, - include_pending=include_pending) - data = task.get() # api call('balance', address, token_symbol, include_pending) + data = call("balance", address,token_symbol, include_pending) log.debug(data) #[{'address': '3ff776b6f888980def9d4220858803f9dc5e341e', 'converters': [], 'balance_network': 0}] - return list(map(lambda b : TokenBalance(**b), data)) + return list(map(lambda b: TokenBalance(**b), data)) -def create_account_post(password, register): # noqa: E501 +def create_account_post(password="", register=True): """create_account_post - Creates a new blockchain address # noqa: E501 + Creates a new blockchain address :param password: :type password: str :param register: :type register: bool - :rtype: Model0xAddress + :return: Address of the new account + :rtype: string """ data = call("create_account", password, register) return data -def list_transactions(address, limit=10): # noqa: E501 +def list_transactions(address, limit=10): """list_transactions - Retrieve Address Balance # noqa: E501 + Retrieve Address Balance :param address: :type address: dict | bytes @@ -117,19 +54,15 @@ def list_transactions(address, limit=10): # noqa: E501 :rtype: Token """ - api = Api( - chain_spec, - queue=celery_queue, - ) data = call('list', address, limit) # data = task.get() - return data + return list(map(lambda t: Transaction(**t), data)) -def transfer(from_address, to_address, value, token_symbol): # noqa: E501 +def transfer(from_address, to_address, value, token_symbol): """transfer - Performs a transfer of ERC20 tokens from one address to another. # noqa: E501 + Performs a transfer of ERC20 tokens from one address to another. :param from_address: :type from_address: dict | bytes @@ -140,24 +73,19 @@ def transfer(from_address, to_address, value, token_symbol): # noqa: E501 :param token_symbol: :type token_symbol: str - :rtype: Token + :return: Transaction hash for tranfer operation + :rtype: str, 0x-hex """ - api = Api( - chain_spec, - queue=celery_queue, - ) - t = api.transfer(from_address, to_address, - int(value * (10**6)), token_symbol) - log.debug(f"t {t}") - log.debug(f"transfer {t.get_leaf()}") - log.debug(f"transfer {t.successful()}") - return t.get() + data = call('transfer', from_address, to_address, + int(value * (10**6)), token_symbol) + + return data -def transfer_from(from_address, to_address, value, token_symbol, spender_address): # noqa: E501 +def transfer_from(from_address, to_address, value, token_symbol, spender_address): """transfer_from - Performs a transfer of ERC20 tokens by one address on behalf of another address to a third party. # noqa: E501 + Performs a transfer of ERC20 tokens by one address on behalf of another address to a third party. :param from_address: Ethereum address of sender :type from_address: dict | bytes @@ -170,18 +98,10 @@ def transfer_from(from_address, to_address, value, token_symbol, spender_address :param spender_address: Ethereum address of recipient :type spender_address: dict | bytes - :rtype: Token + :return: Transaction hash for transfer operation + :rtype: str, 0x-hex """ - api = Api( - chain_spec, - queue=celery_queue, - ) - t = api.transfer_from(from_address, to_address, - int(value * (10**6)), token_symbol, spender_address) - log.debug(f"t {t}") - log.debug(f"transfer {t.get_leaf()}") - log.debug(f"transfer {t.successful()}") - return t.get() - + data = call("transfer_from", from_address, to_address, int(value * (10**6)), token_symbol, spender_address) + return data diff --git a/apps/cic-eth/cic_eth/server/controllers/token_controller.py b/apps/cic-eth/cic_eth/server/controllers/token_controller.py index f8ad01cd..876bdda7 100644 --- a/apps/cic-eth/cic_eth/server/controllers/token_controller.py +++ b/apps/cic-eth/cic_eth/server/controllers/token_controller.py @@ -1,37 +1,17 @@ import logging -import connexion -import six -from cic_eth.api.api_task import Api -from cic_eth.graphql.config import config -from cic_eth.server import util +from cic_eth.server.celery_helper import call from cic_eth.server.models import Token -from cic_eth.server.models.token import Token # noqa: E501 log = logging.getLogger(__name__) -chain_spec = config.get('CHAIN_SPEC') -celery_queue = config.get('CELERY_QUEUE') - -api = Api( - chain_spec, - queue=celery_queue, -) - -def get_default_token(): # noqa: E501 - """get_default_token - - Retrieve transactions # noqa: E501 - +def get_default_token(): + """Retrieves the default fallback token of the custodial network :rtype: Token """ - task = api.default_token() - data = task.get() # api call('balance', address, token_symbol, include_pending) - task = api.default_token() - data = task.get() - print(data) + data = call("default_token") log.debug(data) return Token(address=data['address'], symbol=data['symbol'], decimals=data['decimals'], name=data['name']) diff --git a/apps/cic-eth/cic_eth/server/models/__init__.py b/apps/cic-eth/cic_eth/server/models/__init__.py index 34bc97a1..d858e083 100644 --- a/apps/cic-eth/cic_eth/server/models/__init__.py +++ b/apps/cic-eth/cic_eth/server/models/__init__.py @@ -5,3 +5,4 @@ from __future__ import absolute_import # import models into model package from cic_eth.server.models.token import Token from cic_eth.server.models.token_balance import TokenBalance +from cic_eth.server.models.transaction import Transaction diff --git a/apps/cic-eth/cic_eth/server/models/base_model_.py b/apps/cic-eth/cic_eth/server/models/base_model_.py index bbd3bbfb..75b16dcf 100644 --- a/apps/cic-eth/cic_eth/server/models/base_model_.py +++ b/apps/cic-eth/cic_eth/server/models/base_model_.py @@ -67,3 +67,4 @@ class Model(object): def __ne__(self, other): """Returns true if both objects are not equal""" return not self == other + diff --git a/apps/cic-eth/cic_eth/server/models/token.py b/apps/cic-eth/cic_eth/server/models/token.py index c64f1018..05f8d584 100644 --- a/apps/cic-eth/cic_eth/server/models/token.py +++ b/apps/cic-eth/cic_eth/server/models/token.py @@ -15,16 +15,16 @@ class Token(Model): Do not edit the class manually. """ - def __init__(self, symbol: str = None, address: str = None, name: str = None, decimals: str = None): # noqa: E501 + def __init__(self, symbol: str = None, address: str = None, name: str = None, decimals: str = None): """Token - a model defined in Swagger - :param symbol: The symbol of this Token. # noqa: E501 + :param symbol: The symbol of this Token. :type symbol: str - :param address: The address of this Token. # noqa: E501 + :param address: The address of this Token. :type address: str - :param name: The name of this Token. # noqa: E501 + :param name: The name of this Token. :type name: str - :param decimals: The decimals of this Token. # noqa: E501 + :param decimals: The decimals of this Token. :type decimals: str """ self.swagger_types = { @@ -51,7 +51,7 @@ class Token(Model): :param dikt: A dict. :type: dict - :return: The Token of this Token. # noqa: E501 + :return: The Token of this Token. :rtype: Token """ return util.deserialize_model(dikt, cls) @@ -60,7 +60,7 @@ class Token(Model): def symbol(self) -> str: """Gets the symbol of this Token. - Token Symbol # noqa: E501 + Token Symbol :return: The symbol of this Token. :rtype: str @@ -71,7 +71,7 @@ class Token(Model): def symbol(self, symbol: str): """Sets the symbol of this Token. - Token Symbol # noqa: E501 + Token Symbol :param symbol: The symbol of this Token. :type symbol: str @@ -83,7 +83,7 @@ class Token(Model): def address(self) -> str: """Gets the address of this Token. - Token Address # noqa: E501 + Token Address :return: The address of this Token. :rtype: str @@ -94,7 +94,7 @@ class Token(Model): def address(self, address: str): """Sets the address of this Token. - Token Address # noqa: E501 + Token Address :param address: The address of this Token. :type address: str @@ -106,7 +106,7 @@ class Token(Model): def name(self) -> str: """Gets the name of this Token. - Token Name # noqa: E501 + Token Name :return: The name of this Token. :rtype: str @@ -117,7 +117,7 @@ class Token(Model): def name(self, name: str): """Sets the name of this Token. - Token Name # noqa: E501 + Token Name :param name: The name of this Token. :type name: str @@ -129,7 +129,7 @@ class Token(Model): def decimals(self) -> str: """Gets the decimals of this Token. - Decimals # noqa: E501 + Decimals :return: The decimals of this Token. :rtype: str @@ -140,7 +140,7 @@ class Token(Model): def decimals(self, decimals: str): """Sets the decimals of this Token. - Decimals # noqa: E501 + Decimals :param decimals: The decimals of this Token. :type decimals: str diff --git a/apps/cic-eth/cic_eth/server/models/token_balance.py b/apps/cic-eth/cic_eth/server/models/token_balance.py index 234e2ffa..1ec5a7d5 100644 --- a/apps/cic-eth/cic_eth/server/models/token_balance.py +++ b/apps/cic-eth/cic_eth/server/models/token_balance.py @@ -15,20 +15,20 @@ class TokenBalance(Model): Do not edit the class manually. """ - def __init__(self, address: str = None, converters: List[str] = None, balance_network: int = None, balance_incoming: int = None, balance_outgoing: int = None): # noqa: E501 + def __init__(self, address: str = None, converters: List[str] = None, balance_network: int = None, balance_incoming: int = None, balance_outgoing: int = None): """TokenBalance - a model defined in Swagger - :param address: The address of this TokenBalance. # noqa: E501 + :param address: The address of this TokenBalance. :type address: str - :param converters: The converters of this TokenBalance. # noqa: E501 + :param converters: The converters of this TokenBalance. :type converters: List[str] - :param balance_network: The balance_network of this TokenBalance. # noqa: E501 + :param balance_network: The balance_network of this TokenBalance. :type balance_network: int - :param balance_incoming: The balance_incoming of this TokenBalance. # noqa: E501 + :param balance_incoming: The balance_incoming of this TokenBalance. :type balance_incoming: int - :param balance_outgoing: The balance_outgoing of this TokenBalance. # noqa: E501 + :param balance_outgoing: The balance_outgoing of this TokenBalance. :type balance_outgoing: int - :param balance_available: The balance_available of this TokenBalance. # noqa: E501 + :param balance_available: The balance_available of this TokenBalance. :type balance_available: int """ self.swagger_types = { @@ -53,7 +53,8 @@ class TokenBalance(Model): self._balance_network = balance_network self._balance_incoming = balance_incoming self._balance_outgoing = balance_outgoing - self._balance_available = int(balance_network) + int(balance_incoming) - int(balance_outgoing) + self._balance_available = int( + balance_network) + int(balance_incoming) - int(balance_outgoing) @classmethod def from_dict(cls, dikt) -> 'TokenBalance': @@ -61,7 +62,7 @@ class TokenBalance(Model): :param dikt: A dict. :type: dict - :return: The TokenBalance of this TokenBalance. # noqa: E501 + :return: The TokenBalance of this TokenBalance. :rtype: TokenBalance """ return util.deserialize_model(dikt, cls) diff --git a/apps/cic-eth/cic_eth/server/models/transaction.py b/apps/cic-eth/cic_eth/server/models/transaction.py new file mode 100644 index 00000000..7747edd6 --- /dev/null +++ b/apps/cic-eth/cic_eth/server/models/transaction.py @@ -0,0 +1,609 @@ +# coding: utf-8 + +from __future__ import absolute_import + +from datetime import date, datetime +from typing import Dict, List + +from cic_eth.server import util +from cic_eth.server.models.base_model_ import Model + + +class Transaction(Model): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + + def __init__(self, block_number: int = None, date_checked: str = None, date_created: str = None, date_updated: str = None, destination_token: str = None, destination_token_decimals: int = None, destination_token_symbol: str = None, from_value: int = None, hash: str = None, nonce: int = None, recipient: str = None, sender: str = None, signed_tx: str = None, source_token: str = None, source_token_decimals: int = None, source_token_symbol: str = None, status: str = None, status_code: int = None, timestamp: int = None, to_value: int = None, tx_hash: str = None, tx_index: int = None): + """Transaction - a model defined in Swagger + + :param block_number: The block_number of this Transaction. + :type block_number: int + :param date_checked: The date_checked of this Transaction. + :type date_checked: str + :param date_created: The date_created of this Transaction. + :type date_created: str + :param date_updated: The date_updated of this Transaction. + :type date_updated: str + :param destination_token: The destination_token of this Transaction. + :type destination_token: str + :param destination_token_decimals: The destination_token_decimals of this Transaction. + :type destination_token_decimals: int + :param destination_token_symbol: The destination_token_symbol of this Transaction. + :type destination_token_symbol: str + :param from_value: The from_value of this Transaction. + :type from_value: int + :param hash: The hash of this Transaction. + :type hash: str + :param nonce: The nonce of this Transaction. + :type nonce: int + :param recipient: The recipient of this Transaction. + :type recipient: str + :param sender: The sender of this Transaction. + :type sender: str + :param signed_tx: The signed_tx of this Transaction. + :type signed_tx: str + :param source_token: The source_token of this Transaction. + :type source_token: str + :param source_token_decimals: The source_token_decimals of this Transaction. + :type source_token_decimals: int + :param source_token_symbol: The source_token_symbol of this Transaction. + :type source_token_symbol: str + :param status: The status of this Transaction. + :type status: str + :param status_code: The status_code of this Transaction. + :type status_code: int + :param timestamp: The timestamp of this Transaction. + :type timestamp: int + :param to_value: The to_value of this Transaction. + :type to_value: int + :param tx_hash: The tx_hash of this Transaction. + :type tx_hash: str + :param tx_index: The tx_index of this Transaction. + :type tx_index: int + """ + self.swagger_types = { + 'block_number': int, + 'date_checked': str, + 'date_created': str, + 'date_updated': str, + 'destination_token': str, + 'destination_token_decimals': int, + 'destination_token_symbol': str, + 'from_value': int, + 'hash': str, + 'nonce': int, + 'recipient': str, + 'sender': str, + 'signed_tx': str, + 'source_token': str, + 'source_token_decimals': int, + 'source_token_symbol': str, + 'status': str, + 'status_code': int, + 'timestamp': int, + 'to_value': int, + 'tx_hash': str, + 'tx_index': int + } + + self.attribute_map = { + 'block_number': 'block_number', + 'date_checked': 'date_checked', + 'date_created': 'date_created', + 'date_updated': 'date_updated', + 'destination_token': 'destination_token', + 'destination_token_decimals': 'destination_token_decimals', + 'destination_token_symbol': 'destination_token_symbol', + 'from_value': 'from_value', + 'hash': 'hash', + 'nonce': 'nonce', + 'recipient': 'recipient', + 'sender': 'sender', + 'signed_tx': 'signed_tx', + 'source_token': 'source_token', + 'source_token_decimals': 'source_token_decimals', + 'source_token_symbol': 'source_token_symbol', + 'status': 'status', + 'status_code': 'status_code', + 'timestamp': 'timestamp', + 'to_value': 'to_value', + 'tx_hash': 'tx_hash', + 'tx_index': 'tx_index' + } + self._block_number = block_number + self._date_checked = date_checked + self._date_created = date_created + self._date_updated = date_updated + self._destination_token = destination_token + self._destination_token_decimals = destination_token_decimals + self._destination_token_symbol = destination_token_symbol + self._from_value = from_value + self._hash = hash + self._nonce = nonce + self._recipient = recipient + self._sender = sender + self._signed_tx = signed_tx + self._source_token = source_token + self._source_token_decimals = source_token_decimals + self._source_token_symbol = source_token_symbol + self._status = status + self._status_code = status_code + self._timestamp = timestamp + self._to_value = to_value + self._tx_hash = tx_hash + self._tx_index = tx_index + + @classmethod + def from_dict(cls, dikt) -> 'Transaction': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The Transaction of this Transaction. + :rtype: Transaction + """ + return util.deserialize_model(dikt, cls) + + @property + def block_number(self) -> int: + """Gets the block_number of this Transaction. + + + :return: The block_number of this Transaction. + :rtype: int + """ + return self._block_number + + @block_number.setter + def block_number(self, block_number: int): + """Sets the block_number of this Transaction. + + + :param block_number: The block_number of this Transaction. + :type block_number: int + """ + + self._block_number = block_number + + @property + def date_checked(self) -> str: + """Gets the date_checked of this Transaction. + + + :return: The date_checked of this Transaction. + :rtype: str + """ + return self._date_checked + + @date_checked.setter + def date_checked(self, date_checked: str): + """Sets the date_checked of this Transaction. + + + :param date_checked: The date_checked of this Transaction. + :type date_checked: str + """ + + self._date_checked = date_checked + + @property + def date_created(self) -> str: + """Gets the date_created of this Transaction. + + + :return: The date_created of this Transaction. + :rtype: str + """ + return self._date_created + + @date_created.setter + def date_created(self, date_created: str): + """Sets the date_created of this Transaction. + + + :param date_created: The date_created of this Transaction. + :type date_created: str + """ + + self._date_created = date_created + + @property + def date_updated(self) -> str: + """Gets the date_updated of this Transaction. + + + :return: The date_updated of this Transaction. + :rtype: str + """ + return self._date_updated + + @date_updated.setter + def date_updated(self, date_updated: str): + """Sets the date_updated of this Transaction. + + + :param date_updated: The date_updated of this Transaction. + :type date_updated: str + """ + + self._date_updated = date_updated + + @property + def destination_token(self) -> str: + """Gets the destination_token of this Transaction. + + + :return: The destination_token of this Transaction. + :rtype: str + """ + return self._destination_token + + @destination_token.setter + def destination_token(self, destination_token: str): + """Sets the destination_token of this Transaction. + + + :param destination_token: The destination_token of this Transaction. + :type destination_token: str + """ + + self._destination_token = destination_token + + @property + def destination_token_decimals(self) -> int: + """Gets the destination_token_decimals of this Transaction. + + + :return: The destination_token_decimals of this Transaction. + :rtype: int + """ + return self._destination_token_decimals + + @destination_token_decimals.setter + def destination_token_decimals(self, destination_token_decimals: int): + """Sets the destination_token_decimals of this Transaction. + + + :param destination_token_decimals: The destination_token_decimals of this Transaction. + :type destination_token_decimals: int + """ + + self._destination_token_decimals = destination_token_decimals + + @property + def destination_token_symbol(self) -> str: + """Gets the destination_token_symbol of this Transaction. + + + :return: The destination_token_symbol of this Transaction. + :rtype: str + """ + return self._destination_token_symbol + + @destination_token_symbol.setter + def destination_token_symbol(self, destination_token_symbol: str): + """Sets the destination_token_symbol of this Transaction. + + + :param destination_token_symbol: The destination_token_symbol of this Transaction. + :type destination_token_symbol: str + """ + + self._destination_token_symbol = destination_token_symbol + + @property + def from_value(self) -> int: + """Gets the from_value of this Transaction. + + + :return: The from_value of this Transaction. + :rtype: int + """ + return self._from_value + + @from_value.setter + def from_value(self, from_value: int): + """Sets the from_value of this Transaction. + + + :param from_value: The from_value of this Transaction. + :type from_value: int + """ + + self._from_value = from_value + + @property + def hash(self) -> str: + """Gets the hash of this Transaction. + + + :return: The hash of this Transaction. + :rtype: str + """ + return self._hash + + @hash.setter + def hash(self, hash: str): + """Sets the hash of this Transaction. + + + :param hash: The hash of this Transaction. + :type hash: str + """ + + self._hash = hash + + @property + def nonce(self) -> int: + """Gets the nonce of this Transaction. + + + :return: The nonce of this Transaction. + :rtype: int + """ + return self._nonce + + @nonce.setter + def nonce(self, nonce: int): + """Sets the nonce of this Transaction. + + + :param nonce: The nonce of this Transaction. + :type nonce: int + """ + + self._nonce = nonce + + @property + def recipient(self) -> str: + """Gets the recipient of this Transaction. + + + :return: The recipient of this Transaction. + :rtype: str + """ + return self._recipient + + @recipient.setter + def recipient(self, recipient: str): + """Sets the recipient of this Transaction. + + + :param recipient: The recipient of this Transaction. + :type recipient: str + """ + + self._recipient = recipient + + @property + def sender(self) -> str: + """Gets the sender of this Transaction. + + + :return: The sender of this Transaction. + :rtype: str + """ + return self._sender + + @sender.setter + def sender(self, sender: str): + """Sets the sender of this Transaction. + + + :param sender: The sender of this Transaction. + :type sender: str + """ + + self._sender = sender + + @property + def signed_tx(self) -> str: + """Gets the signed_tx of this Transaction. + + + :return: The signed_tx of this Transaction. + :rtype: str + """ + return self._signed_tx + + @signed_tx.setter + def signed_tx(self, signed_tx: str): + """Sets the signed_tx of this Transaction. + + + :param signed_tx: The signed_tx of this Transaction. + :type signed_tx: str + """ + + self._signed_tx = signed_tx + + @property + def source_token(self) -> str: + """Gets the source_token of this Transaction. + + + :return: The source_token of this Transaction. + :rtype: str + """ + return self._source_token + + @source_token.setter + def source_token(self, source_token: str): + """Sets the source_token of this Transaction. + + + :param source_token: The source_token of this Transaction. + :type source_token: str + """ + + self._source_token = source_token + + @property + def source_token_decimals(self) -> int: + """Gets the source_token_decimals of this Transaction. + + + :return: The source_token_decimals of this Transaction. + :rtype: int + """ + return self._source_token_decimals + + @source_token_decimals.setter + def source_token_decimals(self, source_token_decimals: int): + """Sets the source_token_decimals of this Transaction. + + + :param source_token_decimals: The source_token_decimals of this Transaction. + :type source_token_decimals: int + """ + + self._source_token_decimals = source_token_decimals + + @property + def source_token_symbol(self) -> str: + """Gets the source_token_symbol of this Transaction. + + + :return: The source_token_symbol of this Transaction. + :rtype: str + """ + return self._source_token_symbol + + @source_token_symbol.setter + def source_token_symbol(self, source_token_symbol: str): + """Sets the source_token_symbol of this Transaction. + + + :param source_token_symbol: The source_token_symbol of this Transaction. + :type source_token_symbol: str + """ + + self._source_token_symbol = source_token_symbol + + @property + def status(self) -> str: + """Gets the status of this Transaction. + + + :return: The status of this Transaction. + :rtype: str + """ + return self._status + + @status.setter + def status(self, status: str): + """Sets the status of this Transaction. + + + :param status: The status of this Transaction. + :type status: str + """ + + self._status = status + + @property + def status_code(self) -> int: + """Gets the status_code of this Transaction. + + + :return: The status_code of this Transaction. + :rtype: int + """ + return self._status_code + + @status_code.setter + def status_code(self, status_code: int): + """Sets the status_code of this Transaction. + + + :param status_code: The status_code of this Transaction. + :type status_code: int + """ + + self._status_code = status_code + + @property + def timestamp(self) -> int: + """Gets the timestamp of this Transaction. + + + :return: The timestamp of this Transaction. + :rtype: int + """ + return self._timestamp + + @timestamp.setter + def timestamp(self, timestamp: int): + """Sets the timestamp of this Transaction. + + + :param timestamp: The timestamp of this Transaction. + :type timestamp: int + """ + + self._timestamp = timestamp + + @property + def to_value(self) -> int: + """Gets the to_value of this Transaction. + + + :return: The to_value of this Transaction. + :rtype: int + """ + return self._to_value + + @to_value.setter + def to_value(self, to_value: int): + """Sets the to_value of this Transaction. + + + :param to_value: The to_value of this Transaction. + :type to_value: int + """ + + self._to_value = to_value + + @property + def tx_hash(self) -> str: + """Gets the tx_hash of this Transaction. + + + :return: The tx_hash of this Transaction. + :rtype: str + """ + return self._tx_hash + + @tx_hash.setter + def tx_hash(self, tx_hash: str): + """Sets the tx_hash of this Transaction. + + + :param tx_hash: The tx_hash of this Transaction. + :type tx_hash: str + """ + + self._tx_hash = tx_hash + + @property + def tx_index(self) -> int: + """Gets the tx_index of this Transaction. + + + :return: The tx_index of this Transaction. + :rtype: int + """ + return self._tx_index + + @tx_index.setter + def tx_index(self, tx_index: int): + """Sets the tx_index of this Transaction. + + + :param tx_index: The tx_index of this Transaction. + :type tx_index: int + """ + + self._tx_index = tx_index diff --git a/apps/cic-eth/cic_eth/server/swagger/swagger.yaml b/apps/cic-eth/cic_eth/server/openapi/server.yaml similarity index 95% rename from apps/cic-eth/cic_eth/server/swagger/swagger.yaml rename to apps/cic-eth/cic_eth/server/openapi/server.yaml index 2ebde8e0..dc089d5a 100644 --- a/apps/cic-eth/cic_eth/server/swagger/swagger.yaml +++ b/apps/cic-eth/cic_eth/server/openapi/server.yaml @@ -103,25 +103,25 @@ paths: parameters: - name: password in: query - required: true + required: false allowReserved: true schema: type: string - name: register in: query - required: true + required: false allowReserved: true schema: type: boolean default: true responses: "200": - description: OK. + description: Address of the new account content: application/json: schema: type: string - example: "e88ba386f0efc7117e8d0d17a750fce492516ecb" + example: "bea54d37f1a469515bda96e116695cedd323c182" x-openapi-router-controller: cic_eth.server.controllers.account_controller /transfer: description: Performs a transfer of ERC20 tokens from one address to another. @@ -136,13 +136,13 @@ paths: required: true schema: type: string - example: "0xe88ba386f0efc7117e8d0d17a750fce492516ecb" + example: "0xbea54d37f1a469515bda96e116695cedd323c182" - name: to_address in: query required: true schema: type: string - example: "0xe88ba386f0efc7117e8d0d17a750fce492516ecb" + example: "0x8264d4c224d0c74c98295bfab2f216c2d7b18c8c" - name: value in: query required: true @@ -155,11 +155,11 @@ paths: type: string responses: "200": - description: OK. + description: Transaction hash for transfer operation content: application/json: schema: - $ref: "#/components/schemas/Token" + type: string x-openapi-router-controller: cic_eth.server.controllers.account_controller /transfer_from: post: @@ -202,11 +202,11 @@ paths: type: string responses: "200": - description: OK. + description: Transaction hash for transfer operation content: application/json: schema: - $ref: "#/components/schemas/Token" + type: string x-openapi-router-controller: cic_eth.server.controllers.account_controller components: schemas: diff --git a/apps/cic-eth/cic_eth/server/test/__init__.py b/apps/cic-eth/cic_eth/server/test/__init__.py deleted file mode 100644 index e72eb1d0..00000000 --- a/apps/cic-eth/cic_eth/server/test/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -import logging - -import connexion -from flask_testing import TestCase - -from cic_eth.server.encoder import JSONEncoder - - -class BaseTestCase(TestCase): - - def create_app(self): - logging.getLogger('connexion.operation').setLevel('ERROR') - app = connexion.App(__name__, specification_dir='../swagger/') - app.app.json_encoder = JSONEncoder - app.add_api('swagger.yaml') - return app.app diff --git a/apps/cic-eth/cic_eth/server/test/test_account_controller.py b/apps/cic-eth/cic_eth/server/test/test_account_controller.py deleted file mode 100644 index 50c13a04..00000000 --- a/apps/cic-eth/cic_eth/server/test/test_account_controller.py +++ /dev/null @@ -1,95 +0,0 @@ -# coding: utf-8 - -from __future__ import absolute_import - -from cic_eth.server.models.model0x_address import Model0xAddress # noqa: E501 -from cic_eth.server.models.token import Token # noqa: E501 -from cic_eth.server.models.token_balance import TokenBalance # noqa: E501 -from cic_eth.server.test import BaseTestCase -from flask import json -from six import BytesIO - - -class TestAccountController(BaseTestCase): - """AccountController integration test stubs""" - - def test_account_balance(self): - """Test case for account_balance - - - """ - query_string = [('address', Model0xAddress()), - ('token_symbol', 'token_symbol_example'), - ('include_pending', True)] - response = self.client.open( - '/balance', - method='GET', - query_string=query_string) - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - def test_create_account_post(self): - """Test case for create_account_post - - - """ - query_string = [('password', 'password_example'), - ('register', true)] - response = self.client.open( - '/create_account', - method='POST', - query_string=query_string) - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - def test_list_transactions(self): - """Test case for list_transactions - - - """ - query_string = [('address', Model0xAddress()), - ('limit', 10)] - response = self.client.open( - '/transactions', - method='GET', - query_string=query_string) - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - def test_transfer(self): - """Test case for transfer - - - """ - query_string = [('from_address', Model0xAddress()), - ('to_address', Model0xAddress()), - ('value', 56), - ('token_symbol', 'token_symbol_example')] - response = self.client.open( - '/transfer', - method='POST', - query_string=query_string) - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - def test_transfer_from(self): - """Test case for transfer_from - - - """ - query_string = [('from_address', Model0xAddress()), - ('to_address', Model0xAddress()), - ('value', 56), - ('token_symbol', 'token_symbol_example'), - ('spender_address', Model0xAddress())] - response = self.client.open( - '/transfer_from', - method='POST', - query_string=query_string) - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - -if __name__ == '__main__': - import unittest - unittest.main() diff --git a/apps/cic-eth/cic_eth/server/test/test_token_controller.py b/apps/cic-eth/cic_eth/server/test/test_token_controller.py deleted file mode 100644 index ffbe7563..00000000 --- a/apps/cic-eth/cic_eth/server/test/test_token_controller.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 - -from __future__ import absolute_import - -from flask import json -from six import BytesIO - -from cic_eth.server.models.token import Token # noqa: E501 -from cic_eth.server.test import BaseTestCase - - -class TestTokenController(BaseTestCase): - """TokenController integration test stubs""" - - def test_get_default_token(self): - """Test case for get_default_token - - - """ - response = self.client.open( - '/token', - method='GET') - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - -if __name__ == '__main__': - import unittest - unittest.main() diff --git a/apps/cic-eth/setup.cfg b/apps/cic-eth/setup.cfg index e67b3035..22fd50d2 100644 --- a/apps/cic-eth/setup.cfg +++ b/apps/cic-eth/setup.cfg @@ -36,6 +36,7 @@ packages = cic_eth.db.models cic_eth.queue cic_eth.ext + cic_eth.server cic_eth.runnable cic_eth.runnable.daemons cic_eth.runnable.daemons.filters diff --git a/apps/cic-eth/tests/server/test_account_controller.py b/apps/cic-eth/tests/server/test_account_controller.py new file mode 100644 index 00000000..33f45c3a --- /dev/null +++ b/apps/cic-eth/tests/server/test_account_controller.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +from __future__ import absolute_import + +import time + +import pytest +from cic_eth.server.app import create_app + + +@pytest.fixture +def client(): + print("Here") + app = create_app({'TESTING': True}) + with app.test_client() as client: + # with app.app_context(): + # init_db() + yield client + + +def test_account(client): + query_string = [('password', ''), + ('register', True)] + response = client.open( + '/create_account', + method='POST', + query_string=query_string) + address_1 = response.get_json() + print(address_1) + + query_string = [('password', ''), + ('register', True)] + response = client.open( + '/create_account', + method='POST', + query_string=query_string) + address_2 = response.get_json() + print(address_2) + time.sleep(10) + # Balance + query_string = [('address', address_1), + ('token_symbol', 'COFE'), + ('include_pending', True)] + response = client.open( + '/balance', + method='GET', + query_string=query_string) + balance = response.get_json() + print(balance) + # Transfer + + query_string = [('from_address', address_1), + ('to_address', address_2), + ('value', 100), + ('token_symbol', 'COFE')] + response = client.open( + '/transfer', + method='POST', + query_string=query_string) + transfer = response.get_json() + print(transfer) + + +# def test_list_transactions(client): +# """Test case for list_transactions + + +# """ +# query_string = [('address', "test_address"), +# ('limit', 10)] +# response = client.open( +# '/transactions', +# method='GET', +# query_string=query_string) +# self.assert200(response, +# 'Response body is : ' + response.data.decode('utf-8')) + + +# def test_transfer(client): +# """Test case for transfer + + +# """ +# query_string = [('from_address', "test_address"), +# ('to_address', "test_address"), +# ('value', 56), +# ('token_symbol', 'token_symbol_example')] +# response = client.open( +# '/transfer', +# method='POST', +# query_string=query_string) +# self.assert200(response, +# 'Response body is : ' + response.data.decode('utf-8')) + + +# def test_transfer_from(client): +# """Test case for transfer_from + + +# """ +# query_string = [('from_address', "test_address"), +# ('to_address', "test_address"), +# ('value', 56), +# ('token_symbol', 'token_symbol_example'), +# ('spender_address', "test_address")] +# response = client.open( +# '/transfer_from', +# method='POST', +# query_string=query_string) +# self.assert200(response, +# 'Response body is : ' + response.data.decode('utf-8')) diff --git a/apps/cic-eth/tests/server/test_token_controller.py b/apps/cic-eth/tests/server/test_token_controller.py new file mode 100644 index 00000000..426ab0e1 --- /dev/null +++ b/apps/cic-eth/tests/server/test_token_controller.py @@ -0,0 +1,43 @@ +# # coding: utf-8 + +# from __future__ import absolute_import + +# import logging + +# import connexion +# from cic_eth.server.encoder import JSONEncoder +# from cic_eth.server.models.token import Token +# from flask import json +# from flask_testing import TestCase +# from six import BytesIO + + +# class BaseTestCase(TestCase): + +# def create_app(self): +# logging.getLogger('connexion.operation').setLevel('ERROR') +# app = connexion.App( +# __name__, specification_dir='../../cic_eth/server/openapi') +# app.app.json_encoder = JSONEncoder +# app.add_api('server.yaml') +# return app.app + + +# class TestTokenController(BaseTestCase): +# """TokenController integration test stubs""" + +# def test_get_default_token(self): +# """Test case for get_default_token + + +# """ +# response = self.client.open( +# '/token', +# method='GET') +# self.assert200(response, +# 'Response body is : ' + response.data.decode('utf-8')) + + +# if __name__ == '__main__': +# import unittest +# unittest.main() diff --git a/apps/contract-migration/docker/Dockerfile b/apps/contract-migration/docker/Dockerfile index 032b884d..2e6e24e0 100644 --- a/apps/contract-migration/docker/Dockerfile +++ b/apps/contract-migration/docker/Dockerfile @@ -1,6 +1,6 @@ ARG DOCKER_REGISTRY="registry.gitlab.com/grassrootseconomics" -FROM $DOCKER_REGISTRY/cic-base-images:python-3.8.6-dev-e8eb2ee2 +FROM registry.gitlab.com/grassrootseconomics/cic-base-images:python-3.8.6-dev-e8eb2ee2 WORKDIR /root diff --git a/docker-compose.yml b/docker-compose.yml index 2b4381d9..073f68cf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -214,7 +214,8 @@ services: set -a if [[ -f /tmp/cic/config/env_reset ]]; then source /tmp/cic/config/env_reset; fi set +a - python /root/cic_eth/server/__main__.py + pip install -r test_requirements.txt + tail -F ./requirements.txt cic-eth-tracker: image: ${DEV_DOCKER_REGISTRY:-registry.gitlab.com/grassrootseconomics/cic-internal-integration}/cic-eth:${TAG:-latest}