Rehabilitate api tests

This commit is contained in:
nolash 2021-03-21 12:18:15 +01:00
parent 65bb4cf66f
commit 453dd47091
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 171 additions and 202 deletions

View File

@ -4,7 +4,8 @@ import logging
# third-party imports
import celery
from cic_registry import zero_address
from chainlib.eth.constant import ZERO_ADDRESS
from chainlib.chain import ChainSpec
# local imports
from cic_eth.db.enum import LockEnum
@ -19,7 +20,7 @@ celery_app = celery.current_app
logg = logging.getLogger()
@celery_app.task(base=CriticalSQLAlchemyTask)
def lock(chained_input, chain_spec_dict, address=zero_address, flags=LockEnum.ALL, tx_hash=None):
def lock(chained_input, chain_spec_dict, address=ZERO_ADDRESS, flags=LockEnum.ALL, tx_hash=None):
"""Task wrapper to set arbitrary locks
:param chain_str: Chain spec string representation
@ -38,7 +39,7 @@ def lock(chained_input, chain_spec_dict, address=zero_address, flags=LockEnum.AL
@celery_app.task(base=CriticalSQLAlchemyTask)
def unlock(chained_input, chain_spec_dict, address=zero_address, flags=LockEnum.ALL):
def unlock(chained_input, chain_spec_dict, address=ZERO_ADDRESS, flags=LockEnum.ALL):
"""Task wrapper to reset arbitrary locks
:param chain_str: Chain spec string representation
@ -57,7 +58,7 @@ def unlock(chained_input, chain_spec_dict, address=zero_address, flags=LockEnum.
@celery_app.task(base=CriticalSQLAlchemyTask)
def lock_send(chained_input, chain_spec_dict, address=zero_address, tx_hash=None):
def lock_send(chained_input, chain_spec_dict, address=ZERO_ADDRESS, tx_hash=None):
"""Task wrapper to set send lock
:param chain_str: Chain spec string representation
@ -74,7 +75,7 @@ def lock_send(chained_input, chain_spec_dict, address=zero_address, tx_hash=None
@celery_app.task(base=CriticalSQLAlchemyTask)
def unlock_send(chained_input, chain_spec_dict, address=zero_address):
def unlock_send(chained_input, chain_spec_dict, address=ZERO_ADDRESS):
"""Task wrapper to reset send lock
:param chain_str: Chain spec string representation
@ -91,7 +92,7 @@ def unlock_send(chained_input, chain_spec_dict, address=zero_address):
@celery_app.task(base=CriticalSQLAlchemyTask)
def lock_queue(chained_input, chain_spec_dict, address=zero_address, tx_hash=None):
def lock_queue(chained_input, chain_spec_dict, address=ZERO_ADDRESS, tx_hash=None):
"""Task wrapper to set queue direct lock
:param chain_str: Chain spec string representation
@ -108,7 +109,7 @@ def lock_queue(chained_input, chain_spec_dict, address=zero_address, tx_hash=Non
@celery_app.task(base=CriticalSQLAlchemyTask)
def unlock_queue(chained_input, chain_spec_dict, address=zero_address):
def unlock_queue(chained_input, chain_spec_dict, address=ZERO_ADDRESS):
"""Task wrapper to reset queue direct lock
:param chain_str: Chain spec string representation
@ -128,7 +129,7 @@ def unlock_queue(chained_input, chain_spec_dict, address=zero_address):
def check_lock(chained_input, chain_spec_dict, lock_flags, address=None):
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
session = SessionBase.create_session()
r = Lock.check(chain_str, lock_flags, address=zero_address, session=session)
r = Lock.check(chain_str, lock_flags, address=ZERO_ADDRESS, session=session)
if address != None:
r |= Lock.check(chain_str, lock_flags, address=address, session=session)
if r > 0:

View File

@ -8,12 +8,10 @@ import logging
# external imports
import celery
#from cic_registry.chain import ChainSpec
from cic_registry import CICRegistry
from chainlib.chain import ChainSpec
# local imports
from cic_eth.eth.factory import TxFactory
from cic_eth.db.enum import LockEnum
app = celery.current_app
@ -87,7 +85,7 @@ class Api:
'cic_eth.admin.ctrl.check_lock',
[
[from_token_symbol, to_token_symbol],
self.chain_str,
self.chain_spec.asdict(),
LockEnum.QUEUE,
from_address,
],
@ -99,7 +97,7 @@ class Api:
queue=self.queue,
)
s_tokens = celery.signature(
'cic_eth.eth.token.resolve_tokens_by_symbol',
'cic_eth.eth.erc20.resolve_tokens_by_symbol',
[
self.chain_str,
],
@ -112,7 +110,7 @@ class Api:
target_return,
minimum_return,
to_address,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -149,7 +147,7 @@ class Api:
'cic_eth.admin.ctrl.check_lock',
[
[from_token_symbol, to_token_symbol],
self.chain_str,
self.chain_spec.asdict(),
LockEnum.QUEUE,
from_address,
],
@ -161,9 +159,9 @@ class Api:
queue=self.queue,
)
s_tokens = celery.signature(
'cic_eth.eth.token.resolve_tokens_by_symbol',
'cic_eth.eth.erc20.resolve_tokens_by_symbol',
[
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -174,7 +172,7 @@ class Api:
target_return,
minimum_return,
from_address,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -208,7 +206,7 @@ class Api:
'cic_eth.admin.ctrl.check_lock',
[
[token_symbol],
self.chain_str,
self.chain_spec.asdict(),
LockEnum.QUEUE,
from_address,
],
@ -222,19 +220,19 @@ class Api:
queue=self.queue,
)
s_tokens = celery.signature(
'cic_eth.eth.token.resolve_tokens_by_symbol',
'cic_eth.eth.erc20.resolve_tokens_by_symbol',
[
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
s_transfer = celery.signature(
'cic_eth.eth.token.transfer',
'cic_eth.eth.erc20.transfer',
[
from_address,
to_address,
value,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -266,18 +264,18 @@ class Api:
logg.warning('balance pointlessly called with no callback url')
s_tokens = celery.signature(
'cic_eth.eth.token.resolve_tokens_by_symbol',
'cic_eth.eth.erc20.resolve_tokens_by_symbol',
[
[token_symbol],
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
s_balance = celery.signature(
'cic_eth.eth.token.balance',
'cic_eth.eth.erc20.balance',
[
address,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -293,7 +291,7 @@ class Api:
'cic_eth.queue.balance.balance_incoming',
[
address,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -301,7 +299,7 @@ class Api:
'cic_eth.queue.balance.balance_outgoing',
[
address,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -337,7 +335,7 @@ class Api:
'cic_eth.admin.ctrl.check_lock',
[
password,
self.chain_str,
self.chain_spec.asdict(),
LockEnum.CREATE,
],
queue=self.queue,
@ -345,7 +343,7 @@ class Api:
s_account = celery.signature(
'cic_eth.eth.account.create',
[
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -364,7 +362,7 @@ class Api:
s_register = celery.signature(
'cic_eth.eth.account.register',
[
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -387,7 +385,7 @@ class Api:
'cic_eth.admin.ctrl.check_lock',
[
address,
self.chain_str,
self.chain_spec.asdict(),
LockEnum.QUEUE,
],
queue=self.queue,
@ -402,7 +400,7 @@ class Api:
s_refill = celery.signature(
'cic_eth.eth.tx.refill_gas',
[
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)
@ -445,7 +443,7 @@ class Api:
s_brief = celery.signature(
'cic_eth.ext.tx.tx_collate',
[
self.chain_str,
self.chain_spec.asdict(),
offset,
limit
],
@ -471,7 +469,7 @@ class Api:
'cic_eth.ext.tx.list_tx_by_bloom',
[
address,
self.chain_str,
self.chain_spec.asdict(),
],
queue=self.queue,
)

View File

@ -92,7 +92,7 @@ def unpack_gift(data):
# TODO: Separate out nonce initialization task
@celery_app.task(bind=True, base=CriticalSQLAlchemyAndSignerTask)
def create(self, password, chain_str):
def create(self, password, chain_spec_dict):
"""Creates and stores a new ethereum account in the keystore.
The password is passed on to the wallet backend, no encryption is performed in the task worker.
@ -104,8 +104,7 @@ def create(self, password, chain_str):
:returns: Ethereum address of newly created account
:rtype: str, 0x-hex
"""
chain_spec = ChainSpec.from_chain_str(chain_str)
#c = RpcClient(chain_spec)
chain_spec = ChainSpec.from_dict(chain_spec_dict)
a = None
conn = RPCConnection.connect(chain_spec, 'signer')
o = new_account()

View File

@ -14,6 +14,7 @@ from chainlib.eth.tx import (
TxFormat,
unpack,
)
from cic_eth_registry import CICRegistry
from cic_eth_registry.erc20 import ERC20Token
from hexathon import strip_0x
@ -21,6 +22,7 @@ from hexathon import strip_0x
from cic_eth.registry import safe_registry
from cic_eth.db.models.tx import TxCache
from cic_eth.db.models.base import SessionBase
from cic_eth.db.models.role import AccountRole
from cic_eth.eth import RpcClient
from cic_eth.error import TokenCountError, PermanentTxError, OutOfGasError, NotLocalTxError
from cic_eth.queue.tx import register_tx
@ -40,161 +42,6 @@ from cic_eth.eth.nonce import CustodialTaskNonceOracle
celery_app = celery.current_app
logg = logging.getLogger()
## TODO: fetch from cic-contracts instead when implemented
#contract_function_signatures = {
# 'transfer': 'a9059cbb',
# 'approve': '095ea7b3',
# 'transferfrom': '23b872dd',
# }
#
#
#class TokenTxFactory(TxFactory):
# """Factory for creating ERC20 token transactions.
# """
# def approve(
# self,
# token_address,
# spender_address,
# amount,
# chain_spec,
# uuid,
# session=None,
# ):
# """Create an ERC20 "approve" transaction
#
# :param token_address: ERC20 contract address
# :type token_address: str, 0x-hex
# :param spender_address: Address to approve spending for
# :type spender_address: str, 0x-hex
# :param amount: Amount of tokens to approve
# :type amount: int
# :param chain_spec: Chain spec
# :type chain_spec: cic_registry.chain.ChainSpec
# :returns: Unsigned "approve" transaction in standard Ethereum format
# :rtype: dict
# """
# source_token = self.registry.get_address(chain_spec, token_address)
# source_token_contract = source_token.contract
# tx_approve_buildable = source_token_contract.functions.approve(
# spender_address,
# amount,
# )
# source_token_gas = source_token.gas('transfer')
#
# tx_approve = tx_approve_buildable.buildTransaction({
# 'from': self.address,
# 'gas': source_token_gas,
# 'gasPrice': self.gas_price,
# 'chainId': chain_spec.chain_id(),
# 'nonce': self.next_nonce(uuid, session=session),
# })
# return tx_approve
#
#
# def transfer(
# self,
# token_address,
# Receiver_address,
# value,
# chain_spec,
# uuid,
# session=None,
# ):
# """Create an ERC20 "transfer" transaction
#
# :param token_address: ERC20 contract address
# :type token_address: str, 0x-hex
# :param receiver_address: Address to send tokens to
# :type receiver_address: str, 0x-hex
# :param amount: Amount of tokens to send
# :type amount: int
# :param chain_spec: Chain spec
# :type chain_spec: cic_registry.chain.ChainSpec
# :returns: Unsigned "transfer" transaction in standard Ethereum format
# :rtype: dict
# """
# source_token = self.registry.get_address(chain_spec, token_address)
# source_token_contract = source_token.contract
# transfer_buildable = source_token_contract.functions.transfer(
# receiver_address,
# value,
# )
# source_token_gas = source_token.gas('transfer')
#
# tx_transfer = transfer_buildable.buildTransaction(
# {
# 'from': self.address,
# 'gas': source_token_gas,
# 'gasPrice': self.gas_price,
# 'chainId': chain_spec.chain_id(),
# 'nonce': self.next_nonce(uuid, session=session),
# })
# return tx_transfer
#def unpack_transfer(data):
# """Verifies that a transaction is an "ERC20.transfer" transaction, and extracts call parameters from it.
#
# :param data: Raw input data from Ethereum transaction.
# :type data: str, 0x-hex
# :raises ValueError: Function signature does not match AccountRegister.add
# :returns: Parsed parameters
# :rtype: dict
# """
# data = strip_0x(data)
# f = data[:8]
# if f != contract_function_signatures['transfer']:
# raise ValueError('Invalid transfer data ({})'.format(f))
#
# d = data[8:]
# return {
# 'to': web3.Web3.toChecksumAddress('0x' + d[64-40:64]),
# 'amount': int(d[64:], 16)
# }
#def unpack_transferfrom(data):
# """Verifies that a transaction is an "ERC20.transferFrom" transaction, and extracts call parameters from it.
#
# :param data: Raw input data from Ethereum transaction.
# :type data: str, 0x-hex
# :raises ValueError: Function signature does not match AccountRegister.add
# :returns: Parsed parameters
# :rtype: dict
# """
# data = strip_0x(data)
# f = data[:8]
# if f != contract_function_signatures['transferfrom']:
# raise ValueError('Invalid transferFrom data ({})'.format(f))
#
# d = data[8:]
# return {
# 'from': web3.Web3.toChecksumAddress('0x' + d[64-40:64]),
# 'to': web3.Web3.toChecksumAddress('0x' + d[128-40:128]),
# 'amount': int(d[128:], 16)
# }
#
#
#def unpack_approve(data):
# """Verifies that a transaction is an "ERC20.approve" transaction, and extracts call parameters from it.
#
# :param data: Raw input data from Ethereum transaction.
# :type data: str, 0x-hex
# :raises ValueError: Function signature does not match AccountRegister.add
# :returns: Parsed parameters
# :rtype: dict
# """
# data = strip_0x(data)
# f = data[:8]
# if f != contract_function_signatures['approve']:
# raise ValueError('Invalid approval data ({})'.format(f))
#
# d = data[8:]
# return {
# 'to': web3.Web3.toChecksumAddress('0x' + d[64-40:64]),
# 'amount': int(d[64:], 16)
# }
@celery_app.task(base=CriticalWeb3Task)
def balance(tokens, holder_address, chain_spec_dict):
@ -341,8 +188,8 @@ def approve(self, tokens, holder_address, spender_address, value, chain_spec_dic
return tx_hash_hex
@celery_app.task(base=CriticalWeb3Task)
def resolve_tokens_by_symbol(token_symbols, chain_str):
@celery_app.task(bind=True, base=CriticalWeb3Task)
def resolve_tokens_by_symbol(self, token_symbols, chain_spec_dict):
"""Returns contract addresses of an array of ERC20 token symbols
:param token_symbols: Token symbols to resolve
@ -354,13 +201,17 @@ def resolve_tokens_by_symbol(token_symbols, chain_str):
:rtype: list of str, 0x-hex
"""
tokens = []
chain_spec = ChainSpec.from_chain_str(chain_str)
c = RpcClient(chain_spec)
registry = safe_registry(c.w3)
chain_spec = ChainSpec.from_dict(chain_spec_dict)
rpc = RPCConnection.connect(chain_spec, 'default')
registry = CICRegistry(chain_spec, rpc)
session = self.create_session()
sender_address = AccountRole.get_address('DEFAULT', session)
session.close()
for token_symbol in token_symbols:
token = registry.get_token(chain_spec, token_symbol)
token_address = registry.by_name(token_symbol, sender_address=sender_address)
logg.debug('token {}'.format(token_address))
tokens.append({
'address': token.address(),
'address': token_address,
'converters': [],
})
return tokens

View File

@ -352,7 +352,7 @@ def refill_gas(self, recipient_address, chain_spec_dict):
logg.debug('tx send gas amount {} from provider {} to {}'.format(refill_amount, gas_provider, recipient_address))
(tx_hash_hex, tx_signed_raw_hex) = c.create(gas_provider, recipient_address, refill_amount, tx_format=TxFormat.RLP_SIGNED)
logg.debug('adding queue refill gas tx {}'.format(tx_hash_hex))
cache_task = 'cic_eth.eth.tx.otx_cache_parse_tx'
cache_task = 'cic_eth.eth.tx.cache_gas_data'
register_tx(tx_hash_hex, tx_signed_raw_hex, chain_spec, queue, cache_task=cache_task, session=session)
# add transaction to send queue

View File

@ -11,7 +11,6 @@ logg = logging.getLogger()
# celery fixtures
@pytest.fixture(scope='session')
def celery_includes():
logg.debug('foooooooooooo ')
return [
# 'cic_eth.eth.bancor',
'cic_eth.eth.erc20',

View File

@ -0,0 +1,121 @@
# standard imports
import os
import logging
import time
# external imports
import pytest
import celery
from cic_eth_registry.erc20 import ERC20Token
from chainlib.chain import ChainSpec
# local imports
from cic_eth.api import Api
logg = logging.getLogger(__name__)
def test_account_api(
default_chain_spec,
init_database,
init_eth_rpc,
account_registry,
custodial_roles,
celery_session_worker,
):
api = Api(str(default_chain_spec), callback_param='accounts', callback_task='cic_eth.callbacks.noop.noop', queue=None)
t = api.create_account('', register=False)
t.get_leaf()
assert t.successful()
def test_transfer_api(
default_chain_spec,
eth_rpc,
init_database,
foo_token,
custodial_roles,
agent_roles,
cic_registry,
token_registry_load,
celery_session_worker,
):
#token = CICRegistry.get_address(default_chain_spec, bancor_tokens[0])
foo_token_cache = ERC20Token(eth_rpc, foo_token)
api = Api(str(default_chain_spec), callback_param='transfer', callback_task='cic_eth.callbacks.noop.noop', queue=None)
t = api.transfer(custodial_roles['FOO_TOKEN_GIFTER'], agent_roles['ALICE'], 1024, foo_token_cache.symbol)
t.get_leaf()
assert t.successful()
@pytest.mark.skip()
def test_convert_api(
default_chain_spec,
init_w3,
cic_registry,
init_database,
foo_token,
bar_token,
celery_session_worker,
):
token_alice = CICRegistry.get_address(default_chain_spec, bancor_tokens[0])
token_bob = CICRegistry.get_address(default_chain_spec, bancor_tokens[1])
api = Api(str(default_chain_spec), callback_param='convert', callback_task='cic_eth.callbacks.noop.noop', queue=None)
t = api.convert(custodial_roles['FOO_TOKEN_GIFTER'], 110, 100, foo_token_cache.symbol, bar_token_cache.symbol)
t.get_leaf()
assert t.successful()
@pytest.mark.skip()
def test_convert_transfer_api(
default_chain_spec,
init_w3,
cic_registry,
init_database,
bancor_registry,
bancor_tokens,
celery_session_worker,
):
token_alice = CICRegistry.get_address(default_chain_spec, bancor_tokens[0])
token_bob = CICRegistry.get_address(default_chain_spec, bancor_tokens[1])
api = Api(str(default_chain_spec), callback_param='convert_transfer', callback_task='cic_eth.callbacks.noop.noop', queue=None)
t = api.convert_transfer(init_w3.eth.accounts[2], init_w3.eth.accounts[4], 110, 100, token_alice.symbol(), token_bob.symbol())
t.get()
for r in t.collect():
print(r)
assert t.successful()
def test_refill_gas(
default_chain_spec,
init_database,
eth_empty_accounts,
init_eth_rpc,
custodial_roles,
celery_session_worker,
):
api = Api(str(default_chain_spec), callback_param='refill_gas', callback_task='cic_eth.callbacks.noop.noop', queue=None)
t = api.refill_gas(eth_empty_accounts[0])
t.get()
for r in t.collect():
print(r)
assert t.successful()
def test_ping(
default_chain_spec,
celery_session_worker,
):
api = Api(str(default_chain_spec), callback_param='ping', callback_task='cic_eth.callbacks.noop.noop', queue=None)
t = api.ping('pong')
t.get()
for r in t.collect():
print(r)
assert t.successful()