Merge branch 'lash/allowance' into 'master'
Add allowance check and transferFrom task See merge request grassrootseconomics/cic-internal-integration!203
This commit is contained in:
commit
a075c55957
@ -1,4 +1,4 @@
|
|||||||
cic-base==0.1.3a3+build.4aa03607
|
cic-base==0.1.3a3+build.984b5cff
|
||||||
alembic==1.4.2
|
alembic==1.4.2
|
||||||
confini~=0.3.6rc3
|
confini~=0.3.6rc3
|
||||||
uwsgi==2.0.19.1
|
uwsgi==2.0.19.1
|
||||||
|
@ -6,5 +6,5 @@ sqlparse==0.4.1
|
|||||||
pytest-celery==0.0.0a1
|
pytest-celery==0.0.0a1
|
||||||
eth_tester==0.5.0b3
|
eth_tester==0.5.0b3
|
||||||
py-evm==0.3.0a20
|
py-evm==0.3.0a20
|
||||||
cic_base[full]==0.1.3a3+build.4aa03607
|
cic_base[full]==0.1.3a3+build.984b5cff
|
||||||
sarafu-faucet~=0.0.4a1
|
sarafu-faucet~=0.0.4a1
|
||||||
|
@ -204,6 +204,82 @@ class Api:
|
|||||||
# return t
|
# return t
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_from(self, from_address, to_address, value, token_symbol, spender_address):
|
||||||
|
"""Executes a chain of celery tasks that 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: str, 0x-hex
|
||||||
|
:param to_address: Ethereum address of recipient
|
||||||
|
:type to_address: str, 0x-hex
|
||||||
|
:param value: Estimated return from conversion
|
||||||
|
:type value: int
|
||||||
|
:param token_symbol: ERC20 token symbol of token to send
|
||||||
|
:type token_symbol: str
|
||||||
|
:param spender_address: Ethereum address of recipient
|
||||||
|
:type spender_address: str, 0x-hex
|
||||||
|
:returns: uuid of root task
|
||||||
|
:rtype: celery.Task
|
||||||
|
"""
|
||||||
|
s_check = celery.signature(
|
||||||
|
'cic_eth.admin.ctrl.check_lock',
|
||||||
|
[
|
||||||
|
[token_symbol],
|
||||||
|
self.chain_spec.asdict(),
|
||||||
|
LockEnum.QUEUE,
|
||||||
|
from_address,
|
||||||
|
],
|
||||||
|
queue=self.queue,
|
||||||
|
)
|
||||||
|
s_nonce = celery.signature(
|
||||||
|
'cic_eth.eth.nonce.reserve_nonce',
|
||||||
|
[
|
||||||
|
self.chain_spec.asdict(),
|
||||||
|
from_address,
|
||||||
|
],
|
||||||
|
queue=self.queue,
|
||||||
|
)
|
||||||
|
s_tokens = celery.signature(
|
||||||
|
'cic_eth.eth.erc20.resolve_tokens_by_symbol',
|
||||||
|
[
|
||||||
|
self.chain_spec.asdict(),
|
||||||
|
],
|
||||||
|
queue=self.queue,
|
||||||
|
)
|
||||||
|
s_allow = celery.signature(
|
||||||
|
'cic_eth.eth.erc20.check_allowance',
|
||||||
|
[
|
||||||
|
from_address,
|
||||||
|
value,
|
||||||
|
self.chain_spec.asdict(),
|
||||||
|
spender_address,
|
||||||
|
],
|
||||||
|
queue=self.queue,
|
||||||
|
)
|
||||||
|
s_transfer = celery.signature(
|
||||||
|
'cic_eth.eth.erc20.transfer_from',
|
||||||
|
[
|
||||||
|
from_address,
|
||||||
|
to_address,
|
||||||
|
value,
|
||||||
|
self.chain_spec.asdict(),
|
||||||
|
spender_address,
|
||||||
|
],
|
||||||
|
queue=self.queue,
|
||||||
|
)
|
||||||
|
s_tokens.link(s_allow)
|
||||||
|
s_nonce.link(s_tokens)
|
||||||
|
s_check.link(s_nonce)
|
||||||
|
if self.callback_param != None:
|
||||||
|
s_transfer.link(self.callback_success)
|
||||||
|
s_allow.link(s_transfer).on_error(self.callback_error)
|
||||||
|
else:
|
||||||
|
s_allow.link(s_transfer)
|
||||||
|
|
||||||
|
t = s_check.apply_async(queue=self.queue)
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def transfer(self, from_address, to_address, value, token_symbol):
|
def transfer(self, from_address, to_address, value, token_symbol):
|
||||||
"""Executes a chain of celery tasks that performs a transfer of ERC20 tokens from one address to another.
|
"""Executes a chain of celery tasks that performs a transfer of ERC20 tokens from one address to another.
|
||||||
|
|
||||||
|
@ -80,3 +80,8 @@ class SignerError(SeppukuError):
|
|||||||
class RoleAgencyError(SeppukuError):
|
class RoleAgencyError(SeppukuError):
|
||||||
"""Exception raise when a role cannot perform its function. This is a critical exception
|
"""Exception raise when a role cannot perform its function. This is a critical exception
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class YouAreBrokeError(Exception):
|
||||||
|
"""Exception raised when a value transfer is attempted without access to sufficient funds
|
||||||
|
"""
|
||||||
|
@ -24,6 +24,7 @@ from cic_eth.error import (
|
|||||||
TokenCountError,
|
TokenCountError,
|
||||||
PermanentTxError,
|
PermanentTxError,
|
||||||
OutOfGasError,
|
OutOfGasError,
|
||||||
|
YouAreBrokeError,
|
||||||
)
|
)
|
||||||
from cic_eth.queue.tx import register_tx
|
from cic_eth.queue.tx import register_tx
|
||||||
from cic_eth.eth.gas import (
|
from cic_eth.eth.gas import (
|
||||||
@ -71,6 +72,117 @@ def balance(tokens, holder_address, chain_spec_dict):
|
|||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
|
|
||||||
|
@celery_app.task(bind=True)
|
||||||
|
def check_allowance(self, tokens, holder_address, value, chain_spec_dict, spender_address):
|
||||||
|
"""Best-effort verification that the allowance for a transfer from spend is sufficient.
|
||||||
|
|
||||||
|
:raises YouAreBrokeError: If allowance is insufficient
|
||||||
|
|
||||||
|
:param tokens: Token addresses
|
||||||
|
:type tokens: list of str, 0x-hex
|
||||||
|
:param holder_address: Token holder address
|
||||||
|
:type holder_address: str, 0x-hex
|
||||||
|
:param value: Amount of token, in 'wei'
|
||||||
|
:type value: int
|
||||||
|
:param chain_str: Chain spec string representation
|
||||||
|
:type chain_str: str
|
||||||
|
:param spender_address: Address of account spending on behalf of holder
|
||||||
|
:type spender_address: str, 0x-hex
|
||||||
|
:return: Token list as passed to task
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
logg.debug('tokens {}'.format(tokens))
|
||||||
|
if len(tokens) != 1:
|
||||||
|
raise TokenCountError
|
||||||
|
t = tokens[0]
|
||||||
|
chain_spec = ChainSpec.from_dict(chain_spec_dict)
|
||||||
|
|
||||||
|
rpc = RPCConnection.connect(chain_spec, 'default')
|
||||||
|
|
||||||
|
caller_address = ERC20Token.caller_address
|
||||||
|
c = ERC20(chain_spec)
|
||||||
|
o = c.allowance(t['address'], holder_address, spender_address, sender_address=caller_address)
|
||||||
|
r = rpc.do(o)
|
||||||
|
allowance = c.parse_allowance(r)
|
||||||
|
if allowance < value:
|
||||||
|
errstr = 'allowance {} insufficent to transfer {} {} by {} on behalf of {}'.format(allowance, value, t['symbol'], spender_address, holder_address)
|
||||||
|
logg.error(errstr)
|
||||||
|
raise YouAreBrokeError(errstr)
|
||||||
|
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
|
||||||
|
@celery_app.task(bind=True, base=CriticalSQLAlchemyAndSignerTask)
|
||||||
|
def transfer_from(self, tokens, holder_address, receiver_address, value, chain_spec_dict, spender_address):
|
||||||
|
"""Transfer ERC20 tokens between addresses
|
||||||
|
|
||||||
|
First argument is a list of tokens, to enable the task to be chained to the symbol to token address resolver function. However, it accepts only one token as argument.
|
||||||
|
|
||||||
|
:param tokens: Token addresses
|
||||||
|
:type tokens: list of str, 0x-hex
|
||||||
|
:param holder_address: Token holder address
|
||||||
|
:type holder_address: str, 0x-hex
|
||||||
|
:param receiver_address: Token receiver address
|
||||||
|
:type receiver_address: str, 0x-hex
|
||||||
|
:param value: Amount of token, in 'wei'
|
||||||
|
:type value: int
|
||||||
|
:param chain_str: Chain spec string representation
|
||||||
|
:type chain_str: str
|
||||||
|
:param spender_address: Address of account spending on behalf of holder
|
||||||
|
:type spender_address: str, 0x-hex
|
||||||
|
:raises TokenCountError: Either none or more then one tokens have been passed as tokens argument
|
||||||
|
:return: Transaction hash for tranfer operation
|
||||||
|
:rtype: str, 0x-hex
|
||||||
|
"""
|
||||||
|
# we only allow one token, one transfer
|
||||||
|
logg.debug('tokens {}'.format(tokens))
|
||||||
|
if len(tokens) != 1:
|
||||||
|
raise TokenCountError
|
||||||
|
t = tokens[0]
|
||||||
|
chain_spec = ChainSpec.from_dict(chain_spec_dict)
|
||||||
|
queue = self.request.delivery_info.get('routing_key')
|
||||||
|
|
||||||
|
rpc = RPCConnection.connect(chain_spec, 'default')
|
||||||
|
rpc_signer = RPCConnection.connect(chain_spec, 'signer')
|
||||||
|
|
||||||
|
session = self.create_session()
|
||||||
|
nonce_oracle = CustodialTaskNonceOracle(holder_address, self.request.root_id, session=session)
|
||||||
|
gas_oracle = self.create_gas_oracle(rpc, MaxGasOracle.gas)
|
||||||
|
c = ERC20(chain_spec, signer=rpc_signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
|
||||||
|
try:
|
||||||
|
(tx_hash_hex, tx_signed_raw_hex) = c.transfer_from(t['address'], spender_address, holder_address, receiver_address, value, tx_format=TxFormat.RLP_SIGNED)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
raise SignerError(e)
|
||||||
|
except ConnectionError as e:
|
||||||
|
raise SignerError(e)
|
||||||
|
|
||||||
|
|
||||||
|
rpc_signer.disconnect()
|
||||||
|
rpc.disconnect()
|
||||||
|
|
||||||
|
cache_task = 'cic_eth.eth.erc20.cache_transfer_from_data'
|
||||||
|
|
||||||
|
register_tx(tx_hash_hex, tx_signed_raw_hex, chain_spec, queue, cache_task=cache_task, session=session)
|
||||||
|
session.commit()
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
gas_pair = gas_oracle.get_gas(tx_signed_raw_hex)
|
||||||
|
gas_budget = gas_pair[0] * gas_pair[1]
|
||||||
|
logg.debug('transfer tx {} {} {}'.format(tx_hash_hex, queue, gas_budget))
|
||||||
|
|
||||||
|
s = create_check_gas_task(
|
||||||
|
[tx_signed_raw_hex],
|
||||||
|
chain_spec,
|
||||||
|
holder_address,
|
||||||
|
gas_budget,
|
||||||
|
[tx_hash_hex],
|
||||||
|
queue,
|
||||||
|
)
|
||||||
|
s.apply_async()
|
||||||
|
return tx_hash_hex
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@celery_app.task(bind=True, base=CriticalSQLAlchemyAndSignerTask)
|
@celery_app.task(bind=True, base=CriticalSQLAlchemyAndSignerTask)
|
||||||
def transfer(self, tokens, holder_address, receiver_address, value, chain_spec_dict):
|
def transfer(self, tokens, holder_address, receiver_address, value, chain_spec_dict):
|
||||||
"""Transfer ERC20 tokens between addresses
|
"""Transfer ERC20 tokens between addresses
|
||||||
@ -232,6 +344,7 @@ def resolve_tokens_by_symbol(self, token_symbols, chain_spec_dict):
|
|||||||
logg.debug('token {}'.format(token_address))
|
logg.debug('token {}'.format(token_address))
|
||||||
tokens.append({
|
tokens.append({
|
||||||
'address': token_address,
|
'address': token_address,
|
||||||
|
'symbol': token_symbol,
|
||||||
'converters': [],
|
'converters': [],
|
||||||
})
|
})
|
||||||
rpc.disconnect()
|
rpc.disconnect()
|
||||||
@ -279,6 +392,48 @@ def cache_transfer_data(
|
|||||||
return (tx_hash_hex, cache_id)
|
return (tx_hash_hex, cache_id)
|
||||||
|
|
||||||
|
|
||||||
|
@celery_app.task(base=CriticalSQLAlchemyTask)
|
||||||
|
def cache_transfer_from_data(
|
||||||
|
tx_hash_hex,
|
||||||
|
tx_signed_raw_hex,
|
||||||
|
chain_spec_dict,
|
||||||
|
):
|
||||||
|
"""Helper function for otx_cache_transfer_from
|
||||||
|
|
||||||
|
:param tx_hash_hex: Transaction hash
|
||||||
|
:type tx_hash_hex: str, 0x-hex
|
||||||
|
:param tx: Signed raw transaction
|
||||||
|
:type tx: str, 0x-hex
|
||||||
|
:returns: Transaction hash and id of cache element in storage backend, respectively
|
||||||
|
:rtype: tuple
|
||||||
|
"""
|
||||||
|
chain_spec = ChainSpec.from_dict(chain_spec_dict)
|
||||||
|
tx_signed_raw_bytes = bytes.fromhex(strip_0x(tx_signed_raw_hex))
|
||||||
|
tx = unpack(tx_signed_raw_bytes, chain_spec)
|
||||||
|
|
||||||
|
tx_data = ERC20.parse_transfer_from_request(tx['data'])
|
||||||
|
spender_address = tx_data[0]
|
||||||
|
recipient_address = tx_data[1]
|
||||||
|
token_value = tx_data[2]
|
||||||
|
|
||||||
|
session = SessionBase.create_session()
|
||||||
|
tx_cache = TxCache(
|
||||||
|
tx_hash_hex,
|
||||||
|
tx['from'],
|
||||||
|
recipient_address,
|
||||||
|
tx['to'],
|
||||||
|
tx['to'],
|
||||||
|
token_value,
|
||||||
|
token_value,
|
||||||
|
session=session,
|
||||||
|
)
|
||||||
|
session.add(tx_cache)
|
||||||
|
session.commit()
|
||||||
|
cache_id = tx_cache.id
|
||||||
|
session.close()
|
||||||
|
return (tx_hash_hex, cache_id)
|
||||||
|
|
||||||
|
|
||||||
@celery_app.task(base=CriticalSQLAlchemyTask)
|
@celery_app.task(base=CriticalSQLAlchemyTask)
|
||||||
def cache_approve_data(
|
def cache_approve_data(
|
||||||
tx_hash_hex,
|
tx_hash_hex,
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# third-party imports
|
# external imports
|
||||||
import pytest
|
import pytest
|
||||||
import confini
|
import confini
|
||||||
|
|
||||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
root_dir = os.path.dirname(script_dir)
|
root_dir = os.path.dirname(os.path.dirname(script_dir))
|
||||||
logg = logging.getLogger(__file__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
@ -37,7 +37,8 @@ def init_database(
|
|||||||
database_engine,
|
database_engine,
|
||||||
):
|
):
|
||||||
|
|
||||||
rootdir = os.path.dirname(os.path.dirname(__file__))
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
rootdir = os.path.dirname(os.path.dirname(script_dir))
|
||||||
dbdir = os.path.join(rootdir, 'cic_eth', 'db')
|
dbdir = os.path.join(rootdir, 'cic_eth', 'db')
|
||||||
migrationsdir = os.path.join(dbdir, 'migrations', load_config.get('DATABASE_ENGINE'))
|
migrationsdir = os.path.join(dbdir, 'migrations', load_config.get('DATABASE_ENGINE'))
|
||||||
if not os.path.isdir(migrationsdir):
|
if not os.path.isdir(migrationsdir):
|
@ -10,7 +10,7 @@ version = (
|
|||||||
0,
|
0,
|
||||||
11,
|
11,
|
||||||
1,
|
1,
|
||||||
'alpha.2',
|
'alpha.3',
|
||||||
)
|
)
|
||||||
|
|
||||||
version_object = semver.VersionInfo(
|
version_object = semver.VersionInfo(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
cic-base==0.1.3a3+build.4aa03607
|
cic-base==0.1.3a3+build.984b5cff
|
||||||
celery==4.4.7
|
celery==4.4.7
|
||||||
crypto-dev-signer~=0.4.14b6
|
crypto-dev-signer~=0.4.14b6
|
||||||
confini~=0.3.6rc3
|
confini~=0.3.6rc3
|
||||||
|
@ -17,11 +17,11 @@ root_dir = os.path.dirname(script_dir)
|
|||||||
sys.path.insert(0, root_dir)
|
sys.path.insert(0, root_dir)
|
||||||
|
|
||||||
# assemble fixtures
|
# assemble fixtures
|
||||||
from tests.fixtures_config import *
|
from cic_eth.pytest.fixtures_config import *
|
||||||
from tests.fixtures_database import *
|
from cic_eth.pytest.fixtures_celery import *
|
||||||
from tests.fixtures_celery import *
|
from cic_eth.pytest.fixtures_database import *
|
||||||
from tests.fixtures_role import *
|
from cic_eth.pytest.fixtures_role import *
|
||||||
from tests.fixtures_contract import *
|
from cic_eth.pytest.fixtures_contract import *
|
||||||
from chainlib.eth.pytest import *
|
from chainlib.eth.pytest import *
|
||||||
from eth_contract_registry.pytest import *
|
from eth_contract_registry.pytest import *
|
||||||
from cic_eth_registry.pytest.fixtures_contracts import *
|
from cic_eth_registry.pytest.fixtures_contracts import *
|
||||||
|
@ -1 +1 @@
|
|||||||
from tests.fixtures_celery import *
|
from cic_eth.pytest.fixtures_celery import *
|
||||||
|
@ -13,6 +13,7 @@ from chainlib.eth.tx import (
|
|||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from cic_eth.queue.tx import register_tx
|
from cic_eth.queue.tx import register_tx
|
||||||
|
from cic_eth.error import YouAreBrokeError
|
||||||
|
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
|
|
||||||
@ -167,3 +168,101 @@ def test_erc20_approve_task(
|
|||||||
r = t.get_leaf()
|
r = t.get_leaf()
|
||||||
|
|
||||||
logg.debug('result {}'.format(r))
|
logg.debug('result {}'.format(r))
|
||||||
|
|
||||||
|
|
||||||
|
def test_erc20_transfer_from_task(
|
||||||
|
default_chain_spec,
|
||||||
|
foo_token,
|
||||||
|
agent_roles,
|
||||||
|
custodial_roles,
|
||||||
|
eth_signer,
|
||||||
|
eth_rpc,
|
||||||
|
init_database,
|
||||||
|
celery_session_worker,
|
||||||
|
token_roles,
|
||||||
|
):
|
||||||
|
|
||||||
|
token_object = {
|
||||||
|
'address': foo_token,
|
||||||
|
}
|
||||||
|
transfer_value = 100 * (10 ** 6)
|
||||||
|
|
||||||
|
nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], conn=eth_rpc)
|
||||||
|
c = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle)
|
||||||
|
(tx_hash, o) = c.approve(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], transfer_value)
|
||||||
|
r = eth_rpc.do(o)
|
||||||
|
o = receipt(tx_hash)
|
||||||
|
r = eth_rpc.do(o)
|
||||||
|
assert r['status'] == 1
|
||||||
|
|
||||||
|
s_nonce = celery.signature(
|
||||||
|
'cic_eth.eth.nonce.reserve_nonce',
|
||||||
|
[
|
||||||
|
[token_object],
|
||||||
|
default_chain_spec.asdict(),
|
||||||
|
custodial_roles['FOO_TOKEN_GIFTER'],
|
||||||
|
],
|
||||||
|
queue=None,
|
||||||
|
)
|
||||||
|
s_transfer = celery.signature(
|
||||||
|
'cic_eth.eth.erc20.transfer_from',
|
||||||
|
[
|
||||||
|
custodial_roles['FOO_TOKEN_GIFTER'],
|
||||||
|
agent_roles['BOB'],
|
||||||
|
transfer_value,
|
||||||
|
default_chain_spec.asdict(),
|
||||||
|
agent_roles['ALICE'],
|
||||||
|
],
|
||||||
|
queue=None,
|
||||||
|
)
|
||||||
|
s_nonce.link(s_transfer)
|
||||||
|
t = s_nonce.apply_async()
|
||||||
|
r = t.get_leaf()
|
||||||
|
|
||||||
|
logg.debug('result {}'.format(r))
|
||||||
|
|
||||||
|
|
||||||
|
def test_erc20_allowance_check_task(
|
||||||
|
default_chain_spec,
|
||||||
|
foo_token,
|
||||||
|
agent_roles,
|
||||||
|
custodial_roles,
|
||||||
|
eth_signer,
|
||||||
|
eth_rpc,
|
||||||
|
init_database,
|
||||||
|
celery_session_worker,
|
||||||
|
token_roles,
|
||||||
|
):
|
||||||
|
|
||||||
|
token_object = {
|
||||||
|
'address': foo_token,
|
||||||
|
'symbol': 'FOO',
|
||||||
|
}
|
||||||
|
transfer_value = 100 * (10 ** 6)
|
||||||
|
|
||||||
|
s_check = celery.signature(
|
||||||
|
'cic_eth.eth.erc20.check_allowance',
|
||||||
|
[
|
||||||
|
[token_object],
|
||||||
|
custodial_roles['FOO_TOKEN_GIFTER'],
|
||||||
|
transfer_value,
|
||||||
|
default_chain_spec.asdict(),
|
||||||
|
agent_roles['ALICE']
|
||||||
|
],
|
||||||
|
queue=None,
|
||||||
|
)
|
||||||
|
t = s_check.apply_async()
|
||||||
|
with pytest.raises(YouAreBrokeError):
|
||||||
|
t.get()
|
||||||
|
|
||||||
|
nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], conn=eth_rpc)
|
||||||
|
c = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle)
|
||||||
|
(tx_hash, o) = c.approve(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], transfer_value)
|
||||||
|
r = eth_rpc.do(o)
|
||||||
|
o = receipt(tx_hash)
|
||||||
|
r = eth_rpc.do(o)
|
||||||
|
assert r['status'] == 1
|
||||||
|
|
||||||
|
t = s_check.apply_async()
|
||||||
|
t.get()
|
||||||
|
assert t.successful()
|
||||||
|
@ -9,7 +9,7 @@ import semver
|
|||||||
|
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
|
|
||||||
version = (0, 4, 0, 'alpha.6')
|
version = (0, 4, 0, 'alpha.7')
|
||||||
|
|
||||||
version_object = semver.VersionInfo(
|
version_object = semver.VersionInfo(
|
||||||
major=version[0],
|
major=version[0],
|
||||||
|
@ -1 +1 @@
|
|||||||
cic_base[full_graph]==0.1.3a3+build.4aa03607
|
cic_base[full_graph]==0.1.3a3+build.984b5cff
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
cic_base[full_graph]==0.1.3a3+build.4aa03607
|
cic_base[full_graph]==0.1.3a3+build.984b5cff
|
||||||
cic-eth~=0.11.1a2
|
cic-eth~=0.11.1a3
|
||||||
cic-notify~=0.4.0a6
|
cic-notify~=0.4.0a7
|
||||||
cic-types~=0.1.0a11
|
cic-types~=0.1.0a11
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
cic_base[full_graph]==0.1.3a3+build.4aa03607
|
cic_base[full_graph]==0.1.3a3+build.984b5cff
|
||||||
sarafu-faucet==0.0.4a1
|
sarafu-faucet==0.0.4a1
|
||||||
cic-eth==0.11.1a1
|
cic-eth==0.11.1a1
|
||||||
cic-types==0.1.0a13
|
cic-types==0.1.0a13
|
||||||
|
@ -1 +1 @@
|
|||||||
cic-base==0.1.3a3+build.4aa03607
|
cic-base==0.1.3a3+build.984b5cff
|
||||||
|
@ -14,8 +14,11 @@ repos=(../../cic-cache ../../cic-eth ../../cic-ussd ../../data-seeding ../../cic
|
|||||||
for r in ${repos[@]}; do
|
for r in ${repos[@]}; do
|
||||||
f="$r/requirements.txt"
|
f="$r/requirements.txt"
|
||||||
>&2 echo updating $f
|
>&2 echo updating $f
|
||||||
|
pyreq-update $f base_requirement.txt -vv > $t
|
||||||
|
cp $t $f
|
||||||
|
|
||||||
f="$r/test_requirements.txt"
|
f="$r/test_requirements.txt"
|
||||||
>&2 echo updating $f
|
>&2 echo updating $f
|
||||||
pyreq-update $f base_requirement.txt > $t
|
pyreq-update $f base_requirement.txt -vv > $t
|
||||||
cp $t $f
|
cp $t $f
|
||||||
done
|
done
|
||||||
|
Loading…
Reference in New Issue
Block a user