Rehabilitate erc20 balance task
This commit is contained in:
parent
871cbdcaeb
commit
c245a29a6b
@ -1,26 +1,27 @@
|
|||||||
# standard imports
|
# standard imports
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# third-party imports
|
# external imports
|
||||||
import celery
|
import celery
|
||||||
import requests
|
import requests
|
||||||
import web3
|
import web3
|
||||||
from cic_registry import zero_address
|
from chainlib.eth.constant import ZERO_ADDRESS
|
||||||
from cic_registry.chain import ChainSpec
|
from chainlib.chain import ChainSpec
|
||||||
from hexathon import strip_0x
|
|
||||||
from chainlib.status import Status as TxStatus
|
from chainlib.status import Status as TxStatus
|
||||||
|
from chainlib.connection import RPCConnection
|
||||||
|
from chainlib.eth.erc20 import ERC20
|
||||||
|
from cic_eth_registry.erc20 import ERC20Token
|
||||||
|
from hexathon import strip_0x
|
||||||
|
|
||||||
# platform imports
|
# local imports
|
||||||
from cic_eth.registry import safe_registry
|
from cic_eth.registry import safe_registry
|
||||||
from cic_eth.db.models.tx import TxCache
|
from cic_eth.db.models.tx import TxCache
|
||||||
from cic_eth.db.models.base import SessionBase
|
from cic_eth.db.models.base import SessionBase
|
||||||
from cic_eth.eth import RpcClient
|
from cic_eth.eth import RpcClient
|
||||||
from cic_eth.error import TokenCountError, PermanentTxError, OutOfGasError, NotLocalTxError
|
from cic_eth.error import TokenCountError, PermanentTxError, OutOfGasError, NotLocalTxError
|
||||||
from cic_eth.eth.task import (
|
from cic_eth.queue.tx import register_tx
|
||||||
register_tx,
|
from cic_eth.eth.gas import create_check_gas_task
|
||||||
create_check_gas_task,
|
#from cic_eth.eth.factory import TxFactory
|
||||||
)
|
|
||||||
from cic_eth.eth.factory import TxFactory
|
|
||||||
from cic_eth.eth.util import unpack_signed_raw_tx
|
from cic_eth.eth.util import unpack_signed_raw_tx
|
||||||
from cic_eth.ext.address import translate_address
|
from cic_eth.ext.address import translate_address
|
||||||
from cic_eth.task import (
|
from cic_eth.task import (
|
||||||
@ -32,96 +33,96 @@ from cic_eth.task import (
|
|||||||
celery_app = celery.current_app
|
celery_app = celery.current_app
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
|
|
||||||
# TODO: fetch from cic-contracts instead when implemented
|
## TODO: fetch from cic-contracts instead when implemented
|
||||||
contract_function_signatures = {
|
#contract_function_signatures = {
|
||||||
'transfer': 'a9059cbb',
|
# 'transfer': 'a9059cbb',
|
||||||
'approve': '095ea7b3',
|
# 'approve': '095ea7b3',
|
||||||
'transferfrom': '23b872dd',
|
# 'transferfrom': '23b872dd',
|
||||||
}
|
# }
|
||||||
|
#
|
||||||
|
#
|
||||||
class TokenTxFactory(TxFactory):
|
#class TokenTxFactory(TxFactory):
|
||||||
"""Factory for creating ERC20 token transactions.
|
# """Factory for creating ERC20 token transactions.
|
||||||
"""
|
# """
|
||||||
def approve(
|
# def approve(
|
||||||
self,
|
# self,
|
||||||
token_address,
|
# token_address,
|
||||||
spender_address,
|
# spender_address,
|
||||||
amount,
|
# amount,
|
||||||
chain_spec,
|
# chain_spec,
|
||||||
uuid,
|
# uuid,
|
||||||
session=None,
|
# session=None,
|
||||||
):
|
# ):
|
||||||
"""Create an ERC20 "approve" transaction
|
# """Create an ERC20 "approve" transaction
|
||||||
|
#
|
||||||
:param token_address: ERC20 contract address
|
# :param token_address: ERC20 contract address
|
||||||
:type token_address: str, 0x-hex
|
# :type token_address: str, 0x-hex
|
||||||
:param spender_address: Address to approve spending for
|
# :param spender_address: Address to approve spending for
|
||||||
:type spender_address: str, 0x-hex
|
# :type spender_address: str, 0x-hex
|
||||||
:param amount: Amount of tokens to approve
|
# :param amount: Amount of tokens to approve
|
||||||
:type amount: int
|
# :type amount: int
|
||||||
:param chain_spec: Chain spec
|
# :param chain_spec: Chain spec
|
||||||
:type chain_spec: cic_registry.chain.ChainSpec
|
# :type chain_spec: cic_registry.chain.ChainSpec
|
||||||
:returns: Unsigned "approve" transaction in standard Ethereum format
|
# :returns: Unsigned "approve" transaction in standard Ethereum format
|
||||||
:rtype: dict
|
# :rtype: dict
|
||||||
"""
|
# """
|
||||||
source_token = self.registry.get_address(chain_spec, token_address)
|
# source_token = self.registry.get_address(chain_spec, token_address)
|
||||||
source_token_contract = source_token.contract
|
# source_token_contract = source_token.contract
|
||||||
tx_approve_buildable = source_token_contract.functions.approve(
|
# tx_approve_buildable = source_token_contract.functions.approve(
|
||||||
spender_address,
|
# spender_address,
|
||||||
amount,
|
# amount,
|
||||||
)
|
# )
|
||||||
source_token_gas = source_token.gas('transfer')
|
# source_token_gas = source_token.gas('transfer')
|
||||||
|
#
|
||||||
tx_approve = tx_approve_buildable.buildTransaction({
|
# tx_approve = tx_approve_buildable.buildTransaction({
|
||||||
'from': self.address,
|
# 'from': self.address,
|
||||||
'gas': source_token_gas,
|
# 'gas': source_token_gas,
|
||||||
'gasPrice': self.gas_price,
|
# 'gasPrice': self.gas_price,
|
||||||
'chainId': chain_spec.chain_id(),
|
# 'chainId': chain_spec.chain_id(),
|
||||||
'nonce': self.next_nonce(uuid, session=session),
|
# 'nonce': self.next_nonce(uuid, session=session),
|
||||||
})
|
# })
|
||||||
return tx_approve
|
# return tx_approve
|
||||||
|
#
|
||||||
|
#
|
||||||
def transfer(
|
# def transfer(
|
||||||
self,
|
# self,
|
||||||
token_address,
|
# token_address,
|
||||||
receiver_address,
|
# receiver_address,
|
||||||
value,
|
# value,
|
||||||
chain_spec,
|
# chain_spec,
|
||||||
uuid,
|
# uuid,
|
||||||
session=None,
|
# session=None,
|
||||||
):
|
# ):
|
||||||
"""Create an ERC20 "transfer" transaction
|
# """Create an ERC20 "transfer" transaction
|
||||||
|
#
|
||||||
:param token_address: ERC20 contract address
|
# :param token_address: ERC20 contract address
|
||||||
:type token_address: str, 0x-hex
|
# :type token_address: str, 0x-hex
|
||||||
:param receiver_address: Address to send tokens to
|
# :param receiver_address: Address to send tokens to
|
||||||
:type receiver_address: str, 0x-hex
|
# :type receiver_address: str, 0x-hex
|
||||||
:param amount: Amount of tokens to send
|
# :param amount: Amount of tokens to send
|
||||||
:type amount: int
|
# :type amount: int
|
||||||
:param chain_spec: Chain spec
|
# :param chain_spec: Chain spec
|
||||||
:type chain_spec: cic_registry.chain.ChainSpec
|
# :type chain_spec: cic_registry.chain.ChainSpec
|
||||||
:returns: Unsigned "transfer" transaction in standard Ethereum format
|
# :returns: Unsigned "transfer" transaction in standard Ethereum format
|
||||||
:rtype: dict
|
# :rtype: dict
|
||||||
"""
|
# """
|
||||||
source_token = self.registry.get_address(chain_spec, token_address)
|
# source_token = self.registry.get_address(chain_spec, token_address)
|
||||||
source_token_contract = source_token.contract
|
# source_token_contract = source_token.contract
|
||||||
transfer_buildable = source_token_contract.functions.transfer(
|
# transfer_buildable = source_token_contract.functions.transfer(
|
||||||
receiver_address,
|
# receiver_address,
|
||||||
value,
|
# value,
|
||||||
)
|
# )
|
||||||
source_token_gas = source_token.gas('transfer')
|
# source_token_gas = source_token.gas('transfer')
|
||||||
|
#
|
||||||
tx_transfer = transfer_buildable.buildTransaction(
|
# tx_transfer = transfer_buildable.buildTransaction(
|
||||||
{
|
# {
|
||||||
'from': self.address,
|
# 'from': self.address,
|
||||||
'gas': source_token_gas,
|
# 'gas': source_token_gas,
|
||||||
'gasPrice': self.gas_price,
|
# 'gasPrice': self.gas_price,
|
||||||
'chainId': chain_spec.chain_id(),
|
# 'chainId': chain_spec.chain_id(),
|
||||||
'nonce': self.next_nonce(uuid, session=session),
|
# 'nonce': self.next_nonce(uuid, session=session),
|
||||||
})
|
# })
|
||||||
return tx_transfer
|
# return tx_transfer
|
||||||
|
|
||||||
|
|
||||||
def unpack_transfer(data):
|
def unpack_transfer(data):
|
||||||
@ -189,7 +190,7 @@ def unpack_approve(data):
|
|||||||
|
|
||||||
|
|
||||||
@celery_app.task(base=CriticalWeb3Task)
|
@celery_app.task(base=CriticalWeb3Task)
|
||||||
def balance(tokens, holder_address, chain_str):
|
def balance(tokens, holder_address, chain_spec_dict):
|
||||||
"""Return token balances for a list of tokens for given address
|
"""Return token balances for a list of tokens for given address
|
||||||
|
|
||||||
:param tokens: Token addresses
|
:param tokens: Token addresses
|
||||||
@ -201,14 +202,17 @@ def balance(tokens, holder_address, chain_str):
|
|||||||
:return: List of balances
|
:return: List of balances
|
||||||
:rtype: list of int
|
:rtype: list of int
|
||||||
"""
|
"""
|
||||||
#abi = ContractRegistry.abi('ERC20Token')
|
chain_spec = ChainSpec.from_dict(chain_spec_dict)
|
||||||
chain_spec = ChainSpec.from_chain_str(chain_str)
|
rpc = RPCConnection.connect(chain_spec, 'default')
|
||||||
c = RpcClient(chain_spec)
|
caller_address = ERC20Token.caller_address
|
||||||
registry = safe_registry(c.w3)
|
|
||||||
for t in tokens:
|
for t in tokens:
|
||||||
o = registry.get_address(chain_spec, t['address']).contract
|
address = t['address']
|
||||||
b = o.functions.balanceOf(holder_address).call()
|
token = ERC20Token(rpc, address)
|
||||||
t['balance_network'] = b
|
c = ERC20()
|
||||||
|
o = c.balance_of(address, holder_address, sender_address=caller_address)
|
||||||
|
r = rpc.do(o)
|
||||||
|
t['balance_network'] = c.parse_balance(r)
|
||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
@ -487,8 +491,8 @@ class ExtendedTx:
|
|||||||
self.recipient_label = None
|
self.recipient_label = None
|
||||||
self.source_token_value = 0
|
self.source_token_value = 0
|
||||||
self.destination_token_value = 0
|
self.destination_token_value = 0
|
||||||
self.source_token = zero_address
|
self.source_token = ZERO_ADDRESS
|
||||||
self.destination_token = zero_address
|
self.destination_token = ZERO_ADDRESS
|
||||||
self.source_token_symbol = ''
|
self.source_token_symbol = ''
|
||||||
self.destination_token_symbol = ''
|
self.destination_token_symbol = ''
|
||||||
self.source_token_decimals = ExtendedTx._default_decimals
|
self.source_token_decimals = ExtendedTx._default_decimals
|
@ -1,42 +0,0 @@
|
|||||||
# standard imports
|
|
||||||
import logging
|
|
||||||
|
|
||||||
# local imports
|
|
||||||
from cic_registry import CICRegistry
|
|
||||||
from cic_eth.eth.nonce import NonceOracle
|
|
||||||
from cic_eth.eth import RpcClient
|
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class TxFactory:
|
|
||||||
"""Base class for transaction factory classes.
|
|
||||||
|
|
||||||
:param from_address: Signer address to create transaction on behalf of
|
|
||||||
:type from_address: str, 0x-hex
|
|
||||||
:param rpc_client: RPC connection object to use to acquire account nonce if no record in nonce cache
|
|
||||||
:type rpc_client: cic_eth.eth.rpc.RpcClient
|
|
||||||
"""
|
|
||||||
|
|
||||||
gas_price = 100
|
|
||||||
"""Gas price, updated between batches"""
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, from_address, rpc_client, registry=CICRegistry):
|
|
||||||
self.address = from_address
|
|
||||||
self.registry = registry
|
|
||||||
|
|
||||||
self.default_nonce = rpc_client.w3.eth.getTransactionCount(from_address, 'pending')
|
|
||||||
self.nonce_oracle = NonceOracle(from_address, self.default_nonce)
|
|
||||||
|
|
||||||
TxFactory.gas_price = rpc_client.gas_price()
|
|
||||||
logg.debug('txfactory instance address {} gas price'.format(self.address, self.gas_price))
|
|
||||||
|
|
||||||
|
|
||||||
def next_nonce(self, uuid, session=None):
|
|
||||||
"""Returns the current reserved nonce value, and increments it for next transaction.
|
|
||||||
|
|
||||||
:returns: Nonce
|
|
||||||
:rtype: number
|
|
||||||
"""
|
|
||||||
return self.nonce_oracle.next_by_task_uuid(uuid, session=session)
|
|
@ -215,8 +215,6 @@ def hashes_to_txs(self, tx_hashes):
|
|||||||
|
|
||||||
queue = self.request.delivery_info['routing_key']
|
queue = self.request.delivery_info['routing_key']
|
||||||
|
|
||||||
#otxs = ','.format("'{}'".format(tx_hash) for tx_hash in tx_hashes)
|
|
||||||
|
|
||||||
session = SessionBase.create_session()
|
session = SessionBase.create_session()
|
||||||
q = session.query(Otx.signed_tx)
|
q = session.query(Otx.signed_tx)
|
||||||
q = q.filter(Otx.tx_hash.in_(tx_hashes))
|
q = q.filter(Otx.tx_hash.in_(tx_hashes))
|
||||||
@ -282,16 +280,7 @@ def send(self, txs, chain_spec_dict):
|
|||||||
|
|
||||||
o = raw(tx_hex)
|
o = raw(tx_hex)
|
||||||
conn = RPCConnection.connect(chain_spec, 'default')
|
conn = RPCConnection.connect(chain_spec, 'default')
|
||||||
#try:
|
|
||||||
#r = c.w3.eth.send_raw_transaction(tx_hex)
|
|
||||||
#r = c.w3.eth.sendRawTransaction(tx_hex)
|
|
||||||
conn.do(o)
|
conn.do(o)
|
||||||
#except requests.exceptions.ConnectionError as e:
|
|
||||||
# raise(e)
|
|
||||||
# except Exception as e:
|
|
||||||
# raiser = ParityNodeHandler(chain_spec, queue)
|
|
||||||
# (t, e, m) = raiser.handle(e, tx_hash_hex, tx_hex)
|
|
||||||
# raise e(m)
|
|
||||||
s_set_sent.apply_async()
|
s_set_sent.apply_async()
|
||||||
|
|
||||||
tx_tail = txs[1:]
|
tx_tail = txs[1:]
|
||||||
@ -320,8 +309,13 @@ def refill_gas(self, recipient_address, chain_spec_dict):
|
|||||||
:returns: Transaction hash.
|
:returns: Transaction hash.
|
||||||
:rtype: str, 0x-hex
|
:rtype: str, 0x-hex
|
||||||
"""
|
"""
|
||||||
|
# essentials
|
||||||
chain_spec = ChainSpec.from_dict(chain_spec_dict)
|
chain_spec = ChainSpec.from_dict(chain_spec_dict)
|
||||||
|
queue = self.request.delivery_info.get('routing_key')
|
||||||
|
|
||||||
|
# Determine value of gas tokens to send
|
||||||
|
# if an uncompleted gas refill for the same recipient already exists, we still need to spend the nonce
|
||||||
|
# however, we will perform a 0-value transaction instead
|
||||||
zero_amount = False
|
zero_amount = False
|
||||||
session = SessionBase.create_session()
|
session = SessionBase.create_session()
|
||||||
status_filter = StatusBits.FINAL | StatusBits.NODE_ERROR | StatusBits.NETWORK_ERROR | StatusBits.UNKNOWN_ERROR
|
status_filter = StatusBits.FINAL | StatusBits.NODE_ERROR | StatusBits.NETWORK_ERROR | StatusBits.UNKNOWN_ERROR
|
||||||
@ -336,56 +330,32 @@ def refill_gas(self, recipient_address, chain_spec_dict):
|
|||||||
zero_amount = True
|
zero_amount = True
|
||||||
session.flush()
|
session.flush()
|
||||||
|
|
||||||
queue = self.request.delivery_info.get('routing_key')
|
# finally determine the value to send
|
||||||
|
|
||||||
#c = RpcClient(chain_spec)
|
|
||||||
rpc = RPCConnection.connect(chain_spec, 'default')
|
|
||||||
|
|
||||||
gas_provider = AccountRole.get_address('GAS_GIFTER', session=session)
|
|
||||||
session.flush()
|
|
||||||
|
|
||||||
# Get default nonce to use from network if no nonce has been set
|
|
||||||
# TODO: This step may be redundant as nonce entry is set at account creation time
|
|
||||||
#default_nonce = c.w3.eth.getTransactionCount(c.gas_provider(), 'pending')
|
|
||||||
#o = count_pending(gas_provider)
|
|
||||||
#default_nonce = conn.do(o)
|
|
||||||
|
|
||||||
nonce_oracle = CustodialTaskNonceOracle(gas_provider, self.request.root_id, session=session) #, default_nonce)
|
|
||||||
#nonce = nonce_generator.next(session=session)
|
|
||||||
#nonce = nonce_generator.next_by_task_uuid(self.request.root_id, session=session)
|
|
||||||
rpc_signer = RPCConnection.connect(chain_spec, 'signer')
|
|
||||||
gas_oracle = self.create_gas_oracle(rpc)
|
|
||||||
c = Gas(signer=rpc_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle, chain_id=chain_spec.chain_id())
|
|
||||||
#gas_price = c.gas_price()
|
|
||||||
#gas_limit = c.default_gas_limit
|
|
||||||
refill_amount = 0
|
refill_amount = 0
|
||||||
if not zero_amount:
|
if not zero_amount:
|
||||||
refill_amount = self.safe_gas_refill_amount
|
refill_amount = self.safe_gas_refill_amount
|
||||||
|
|
||||||
logg.debug('tx send gas amount {} from provider {} to {}'.format(refill_amount, gas_provider, recipient_address))
|
# determine sender
|
||||||
# # create and sign transaction
|
gas_provider = AccountRole.get_address('GAS_GIFTER', session=session)
|
||||||
# tx_send_gas = {
|
session.flush()
|
||||||
# 'from': c.gas_provider(),
|
|
||||||
# 'to': recipient_address,
|
|
||||||
# 'gas': gas_limit,
|
|
||||||
# 'gasPrice': gas_price,
|
|
||||||
# 'chainId': chain_spec.chain_id(),
|
|
||||||
# 'nonce': nonce,
|
|
||||||
# 'value': refill_amount,
|
|
||||||
# 'data': '',
|
|
||||||
# }
|
|
||||||
# #tx_send_gas_signed = c.w3.eth.sign_transaction(tx_send_gas)
|
|
||||||
# #tx_hash = web3.Web3.keccak(hexstr=tx_send_gas_signed['raw'])
|
|
||||||
# #tx_hash_hex = tx_hash.hex()
|
|
||||||
# (tx_hash_hex, tx_send_gas_signed) = sign_tx(tx_send_gas)
|
|
||||||
(tx_hash_hex, tx_signed_raw_hex) = c.create(gas_provider, recipient_address, refill_amount, tx_format=TxFormat.RLP_SIGNED)
|
|
||||||
|
|
||||||
# TODO: route this through sign_and_register_tx instead
|
# set up evm RPC connection
|
||||||
|
rpc = RPCConnection.connect(chain_spec, 'default')
|
||||||
|
|
||||||
|
# set up transaction builder
|
||||||
|
nonce_oracle = CustodialTaskNonceOracle(gas_provider, self.request.root_id, session=session)
|
||||||
|
gas_oracle = self.create_gas_oracle(rpc)
|
||||||
|
rpc_signer = RPCConnection.connect(chain_spec, 'signer')
|
||||||
|
c = Gas(signer=rpc_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle, chain_id=chain_spec.chain_id())
|
||||||
|
|
||||||
|
# build and add transaction
|
||||||
|
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))
|
logg.debug('adding queue refill gas tx {}'.format(tx_hash_hex))
|
||||||
#cache_task = 'cic_eth.eth.tx.cache_gas_refill_data'
|
|
||||||
cache_task = 'cic_eth.eth.tx.otx_cache_parse_tx'
|
cache_task = 'cic_eth.eth.tx.otx_cache_parse_tx'
|
||||||
register_tx(tx_hash_hex, tx_signed_raw_hex, chain_spec, queue, cache_task=cache_task, session=session)
|
register_tx(tx_hash_hex, tx_signed_raw_hex, chain_spec, queue, cache_task=cache_task, session=session)
|
||||||
|
|
||||||
|
# add transaction to send queue
|
||||||
s_status = celery.signature(
|
s_status = celery.signature(
|
||||||
'cic_eth.queue.tx.set_ready',
|
'cic_eth.queue.tx.set_ready',
|
||||||
[
|
[
|
||||||
|
@ -13,3 +13,4 @@ from tests.fixtures_role import *
|
|||||||
from chainlib.eth.pytest import *
|
from chainlib.eth.pytest import *
|
||||||
from contract_registry.pytest import *
|
from contract_registry.pytest import *
|
||||||
from cic_eth_registry.pytest.fixtures_contracts import *
|
from cic_eth_registry.pytest.fixtures_contracts import *
|
||||||
|
from cic_eth_registry.pytest.fixtures_tokens import *
|
||||||
|
@ -13,7 +13,7 @@ logg = logging.getLogger()
|
|||||||
def celery_includes():
|
def celery_includes():
|
||||||
return [
|
return [
|
||||||
# 'cic_eth.eth.bancor',
|
# 'cic_eth.eth.bancor',
|
||||||
# 'cic_eth.eth.token',
|
'cic_eth.eth.erc20',
|
||||||
'cic_eth.eth.tx',
|
'cic_eth.eth.tx',
|
||||||
# 'cic_eth.ext.tx',
|
# 'cic_eth.ext.tx',
|
||||||
'cic_eth.queue.tx',
|
'cic_eth.queue.tx',
|
||||||
|
43
apps/cic-eth/tests/task/test_task_erc20.py
Normal file
43
apps/cic-eth/tests/task/test_task_erc20.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# external imports
|
||||||
|
import celery
|
||||||
|
from chainlib.eth.erc20 import ERC20
|
||||||
|
from chainlib.eth.nonce import RPCNonceOracle
|
||||||
|
from chainlib.eth.tx import receipt
|
||||||
|
|
||||||
|
|
||||||
|
def test_erc20_balance(
|
||||||
|
default_chain_spec,
|
||||||
|
foo_token,
|
||||||
|
token_roles,
|
||||||
|
agent_roles,
|
||||||
|
eth_signer,
|
||||||
|
eth_rpc,
|
||||||
|
celery_worker,
|
||||||
|
):
|
||||||
|
|
||||||
|
nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], eth_rpc)
|
||||||
|
c = ERC20(signer=eth_signer, nonce_oracle=nonce_oracle)
|
||||||
|
transfer_value = 100 * (10**6)
|
||||||
|
(tx_hash_hex, o) = c.transfer(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], transfer_value)
|
||||||
|
eth_rpc.do(o)
|
||||||
|
|
||||||
|
o = receipt(tx_hash_hex)
|
||||||
|
r = eth_rpc.do(o)
|
||||||
|
assert r['status'] == 1
|
||||||
|
|
||||||
|
token_object = {
|
||||||
|
'address': foo_token,
|
||||||
|
}
|
||||||
|
s = celery.signature(
|
||||||
|
'cic_eth.eth.erc20.balance',
|
||||||
|
[
|
||||||
|
[token_object],
|
||||||
|
agent_roles['ALICE'],
|
||||||
|
default_chain_spec.asdict(),
|
||||||
|
],
|
||||||
|
queue=None,
|
||||||
|
)
|
||||||
|
t = s.apply_async()
|
||||||
|
r = t.get()
|
||||||
|
assert r[0]['balance_network'] == transfer_value
|
||||||
|
|
Loading…
Reference in New Issue
Block a user