Compare commits
22 Commits
lash/eth-a
...
lash/chain
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea0e2f89d6
|
||
|
|
135bdfe45f
|
||
|
|
c3e2738860
|
||
|
|
7bf21ae6d8
|
||
|
|
882c48b806
|
||
|
|
04e05c9d45
|
||
|
|
839c24f748
|
||
|
|
fbb3609202
|
||
|
|
21b531aa12
|
||
|
|
756124bada
|
||
|
|
ed2521b582 | ||
|
|
395930106a | ||
|
|
ee1452e530 | ||
|
|
8cdaf9f28a
|
||
|
|
402b968b6d | ||
|
|
aa13517534 | ||
|
|
884b18f2f1 | ||
|
|
494a8f3e88 | ||
|
|
1214f605a7 | ||
|
|
0783a6001c | ||
|
|
f9594b766a | ||
|
|
561ae62d5e |
@@ -100,3 +100,4 @@ class SessionBase(Model):
|
||||
logg.debug('destroying session {}'.format(session_key))
|
||||
session.commit()
|
||||
session.close()
|
||||
del SessionBase.localsessions[session_key]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
cic-base==0.1.3a3+build.984b5cff
|
||||
cic-base~=0.2.0a4
|
||||
alembic==1.4.2
|
||||
confini~=0.3.6rc3
|
||||
confini>=0.3.6rc3,<0.5.0
|
||||
uwsgi==2.0.19.1
|
||||
moolb~=0.1.0
|
||||
cic-eth-registry~=0.5.6a1
|
||||
cic-eth-registry~=0.5.6a2
|
||||
SQLAlchemy==1.3.20
|
||||
semver==2.13.0
|
||||
psycopg2==2.8.6
|
||||
celery==4.4.7
|
||||
redis==3.5.3
|
||||
chainsyncer[sql]~=0.0.3a3
|
||||
erc20-faucet~=0.2.2a1
|
||||
chainsyncer[sql]~=0.0.3a5
|
||||
erc20-faucet~=0.2.2a2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SQLAlchemy==1.3.20
|
||||
cic-eth-registry~=0.5.6a1
|
||||
cic-eth-registry>=0.5.6a2,<0.6.0
|
||||
hexathon~=0.0.1a7
|
||||
chainqueue~=0.0.2b5
|
||||
eth-erc20==0.0.10a2
|
||||
chainqueue>=0.0.3a1,<0.1.0
|
||||
eth-erc20>=0.0.10a3,<0.1.0
|
||||
|
||||
@@ -6,6 +6,11 @@ import logging
|
||||
import celery
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.chain import ChainSpec
|
||||
from hexathon import (
|
||||
add_0x,
|
||||
strip_0x,
|
||||
uniform as hex_uniform,
|
||||
)
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.enum import LockEnum
|
||||
@@ -19,6 +24,12 @@ from cic_eth.error import LockedError
|
||||
celery_app = celery.current_app
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def normalize_address(a):
|
||||
if a == None:
|
||||
return None
|
||||
return add_0x(hex_uniform(strip_0x(a)))
|
||||
|
||||
@celery_app.task(base=CriticalSQLAlchemyTask)
|
||||
def lock(chained_input, chain_spec_dict, address=ZERO_ADDRESS, flags=LockEnum.ALL, tx_hash=None):
|
||||
"""Task wrapper to set arbitrary locks
|
||||
@@ -32,6 +43,7 @@ def lock(chained_input, chain_spec_dict, address=ZERO_ADDRESS, flags=LockEnum.AL
|
||||
:returns: New lock state for address
|
||||
:rtype: number
|
||||
"""
|
||||
address = normalize_address(address)
|
||||
chain_str = '::'
|
||||
if chain_spec_dict != None:
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
@@ -53,6 +65,7 @@ def unlock(chained_input, chain_spec_dict, address=ZERO_ADDRESS, flags=LockEnum.
|
||||
:returns: New lock state for address
|
||||
:rtype: number
|
||||
"""
|
||||
address = normalize_address(address)
|
||||
chain_str = '::'
|
||||
if chain_spec_dict != None:
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
@@ -72,6 +85,7 @@ def lock_send(chained_input, chain_spec_dict, address=ZERO_ADDRESS, tx_hash=None
|
||||
:returns: New lock state for address
|
||||
:rtype: number
|
||||
"""
|
||||
address = normalize_address(address)
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
r = Lock.set(chain_str, LockEnum.SEND, address=address, tx_hash=tx_hash)
|
||||
logg.debug('Send locked for {}, flag now {}'.format(address, r))
|
||||
@@ -89,6 +103,7 @@ def unlock_send(chained_input, chain_spec_dict, address=ZERO_ADDRESS):
|
||||
:returns: New lock state for address
|
||||
:rtype: number
|
||||
"""
|
||||
address = normalize_address(address)
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
r = Lock.reset(chain_str, LockEnum.SEND, address=address)
|
||||
logg.debug('Send unlocked for {}, flag now {}'.format(address, r))
|
||||
@@ -106,6 +121,7 @@ def lock_queue(chained_input, chain_spec_dict, address=ZERO_ADDRESS, tx_hash=Non
|
||||
:returns: New lock state for address
|
||||
:rtype: number
|
||||
"""
|
||||
address = normalize_address(address)
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
r = Lock.set(chain_str, LockEnum.QUEUE, address=address, tx_hash=tx_hash)
|
||||
logg.debug('Queue direct locked for {}, flag now {}'.format(address, r))
|
||||
@@ -123,6 +139,7 @@ def unlock_queue(chained_input, chain_spec_dict, address=ZERO_ADDRESS):
|
||||
:returns: New lock state for address
|
||||
:rtype: number
|
||||
"""
|
||||
address = normalize_address(address)
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
r = Lock.reset(chain_str, LockEnum.QUEUE, address=address)
|
||||
logg.debug('Queue direct unlocked for {}, flag now {}'.format(address, r))
|
||||
@@ -131,6 +148,7 @@ def unlock_queue(chained_input, chain_spec_dict, address=ZERO_ADDRESS):
|
||||
|
||||
@celery_app.task(base=CriticalSQLAlchemyTask)
|
||||
def check_lock(chained_input, chain_spec_dict, lock_flags, address=None):
|
||||
address = normalize_address(address)
|
||||
chain_str = '::'
|
||||
if chain_spec_dict != None:
|
||||
chain_str = str(ChainSpec.from_dict(chain_spec_dict))
|
||||
|
||||
@@ -14,7 +14,11 @@ from chainqueue.sql.query import get_tx
|
||||
from chainqueue.sql.state import set_cancel
|
||||
from chainqueue.db.models.otx import Otx
|
||||
from chainqueue.db.models.tx import TxCache
|
||||
from hexathon import strip_0x
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
add_0x,
|
||||
uniform as hex_uniform,
|
||||
)
|
||||
from potaahto.symbols import snake_and_camel
|
||||
|
||||
# local imports
|
||||
@@ -69,15 +73,17 @@ def shift_nonce(self, chainspec_dict, tx_hash_orig_hex, delta=1):
|
||||
|
||||
set_cancel(chain_spec, strip_0x(tx['hash']), manual=True, session=session)
|
||||
|
||||
query_address = add_0x(hex_uniform(strip_0x(address))) # aaaaargh
|
||||
q = session.query(Otx)
|
||||
q = q.join(TxCache)
|
||||
q = q.filter(TxCache.sender==address)
|
||||
q = q.filter(TxCache.sender==query_address)
|
||||
q = q.filter(Otx.nonce>=nonce+delta)
|
||||
q = q.order_by(Otx.nonce.asc())
|
||||
otxs = q.all()
|
||||
|
||||
tx_hashes = []
|
||||
txs = []
|
||||
gas_total = 0
|
||||
for otx in otxs:
|
||||
tx_raw = bytes.fromhex(strip_0x(otx.signed_tx))
|
||||
tx_new = unpack(tx_raw, chain_spec)
|
||||
@@ -89,8 +95,10 @@ def shift_nonce(self, chainspec_dict, tx_hash_orig_hex, delta=1):
|
||||
tx_new['gas_price'] += 1
|
||||
tx_new['gasPrice'] = tx_new['gas_price']
|
||||
tx_new['nonce'] -= delta
|
||||
gas_total += tx_new['gas_price'] * tx_new['gas']
|
||||
|
||||
logg.debug('tx_new {}'.format(tx_new))
|
||||
logg.debug('gas running total {}'.format(gas_total))
|
||||
|
||||
del(tx_new['hash'])
|
||||
del(tx_new['hash_unsigned'])
|
||||
@@ -122,8 +130,10 @@ def shift_nonce(self, chainspec_dict, tx_hash_orig_hex, delta=1):
|
||||
s = create_check_gas_task(
|
||||
txs,
|
||||
chain_spec,
|
||||
tx_new['from'],
|
||||
gas=tx_new['gas'],
|
||||
#tx_new['from'],
|
||||
address,
|
||||
#gas=tx_new['gas'],
|
||||
gas=gas_total,
|
||||
tx_hashes_hex=tx_hashes,
|
||||
queue=queue,
|
||||
)
|
||||
@@ -132,7 +142,8 @@ def shift_nonce(self, chainspec_dict, tx_hash_orig_hex, delta=1):
|
||||
'cic_eth.admin.ctrl.unlock_send',
|
||||
[
|
||||
chain_spec.asdict(),
|
||||
tx_new['from'],
|
||||
address,
|
||||
#tx_new['from'],
|
||||
],
|
||||
queue=queue,
|
||||
)
|
||||
@@ -140,7 +151,8 @@ def shift_nonce(self, chainspec_dict, tx_hash_orig_hex, delta=1):
|
||||
'cic_eth.admin.ctrl.unlock_queue',
|
||||
[
|
||||
chain_spec.asdict(),
|
||||
tx_new['from'],
|
||||
address,
|
||||
#tx_new['from'],
|
||||
],
|
||||
queue=queue,
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ from chainlib.hash import keccak256_hex_to_hex
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
add_0x,
|
||||
uniform as hex_uniform,
|
||||
)
|
||||
from chainlib.eth.gas import balance
|
||||
from chainqueue.db.enum import (
|
||||
@@ -307,6 +308,8 @@ class AdminApi:
|
||||
:param address: Ethereum address to return transactions for
|
||||
:type address: str, 0x-hex
|
||||
"""
|
||||
|
||||
address = add_0x(hex_uniform(strip_0x(address)))
|
||||
last_nonce = -1
|
||||
s = celery.signature(
|
||||
'cic_eth.queue.query.get_account_tx',
|
||||
|
||||
@@ -8,7 +8,8 @@ Create Date: 2021-04-02 18:30:55.398388
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
from chainqueue.db.migrations.sqlalchemy import (
|
||||
#from chainqueue.db.migrations.sqlalchemy import (
|
||||
from chainqueue.db.migrations.default.export import (
|
||||
chainqueue_upgrade,
|
||||
chainqueue_downgrade,
|
||||
)
|
||||
|
||||
@@ -8,7 +8,8 @@ Create Date: 2021-04-02 18:36:44.459603
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
from chainsyncer.db.migrations.sqlalchemy import (
|
||||
#from chainsyncer.db.migrations.sqlalchemy import (
|
||||
from chainsyncer.db.migrations.default.export import (
|
||||
chainsyncer_upgrade,
|
||||
chainsyncer_downgrade,
|
||||
)
|
||||
|
||||
@@ -126,3 +126,4 @@ class SessionBase(Model):
|
||||
logg.debug('commit and destroy session {}'.format(session_key))
|
||||
session.commit()
|
||||
session.close()
|
||||
del SessionBase.localsessions[session_key]
|
||||
|
||||
@@ -23,7 +23,7 @@ from chainlib.error import JSONRPCException
|
||||
from eth_accounts_index.registry import AccountRegistry
|
||||
from eth_accounts_index import AccountsIndex
|
||||
from sarafu_faucet import MinterFaucet
|
||||
from chainqueue.db.models.tx import TxCache
|
||||
from chainqueue.sql.tx import cache_tx_dict
|
||||
|
||||
# local import
|
||||
from cic_eth_registry import CICRegistry
|
||||
@@ -300,20 +300,17 @@ def cache_gift_data(
|
||||
|
||||
session = self.create_session()
|
||||
|
||||
tx_cache = TxCache(
|
||||
tx_hash_hex,
|
||||
tx['from'],
|
||||
tx['to'],
|
||||
ZERO_ADDRESS,
|
||||
ZERO_ADDRESS,
|
||||
0,
|
||||
0,
|
||||
session=session,
|
||||
)
|
||||
tx_dict = {
|
||||
'hash': tx_hash_hex,
|
||||
'from': tx['from'],
|
||||
'to': tx['to'],
|
||||
'source_token': ZERO_ADDRESS,
|
||||
'destination_token': ZERO_ADDRESS,
|
||||
'from_value': 0,
|
||||
'to_value': 0,
|
||||
}
|
||||
|
||||
session.add(tx_cache)
|
||||
session.commit()
|
||||
cache_id = tx_cache.id
|
||||
(tx_dict, cache_id) = cache_tx_dict(tx_dict, session=session)
|
||||
session.close()
|
||||
return (tx_hash_hex, cache_id)
|
||||
|
||||
@@ -342,18 +339,15 @@ def cache_account_data(
|
||||
tx_data = AccountsIndex.parse_add_request(tx['data'])
|
||||
|
||||
session = SessionBase.create_session()
|
||||
tx_cache = TxCache(
|
||||
tx_hash_hex,
|
||||
tx['from'],
|
||||
tx['to'],
|
||||
ZERO_ADDRESS,
|
||||
ZERO_ADDRESS,
|
||||
0,
|
||||
0,
|
||||
session=session,
|
||||
)
|
||||
session.add(tx_cache)
|
||||
session.commit()
|
||||
cache_id = tx_cache.id
|
||||
tx_dict = {
|
||||
'hash': tx_hash_hex,
|
||||
'from': tx['from'],
|
||||
'to': tx['to'],
|
||||
'source_token': ZERO_ADDRESS,
|
||||
'destination_token': ZERO_ADDRESS,
|
||||
'from_value': 0,
|
||||
'to_value': 0,
|
||||
}
|
||||
(tx_dict, cache_id) = cache_tx_dict(tx_dict, session=session)
|
||||
session.close()
|
||||
return (tx_hash_hex, cache_id)
|
||||
|
||||
@@ -1,385 +0,0 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import celery
|
||||
import web3
|
||||
from cic_registry import CICRegistry
|
||||
from cic_registry.chain import ChainSpec
|
||||
|
||||
# local imports
|
||||
from cic_eth.db import SessionBase
|
||||
from cic_eth.db.models.convert import TxConvertTransfer
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.db.models.tx import TxCache
|
||||
from cic_eth.eth.task import sign_and_register_tx
|
||||
from cic_eth.eth.task import create_check_gas_and_send_task
|
||||
from cic_eth.eth.token import TokenTxFactory
|
||||
from cic_eth.eth.factory import TxFactory
|
||||
from cic_eth.eth.util import unpack_signed_raw_tx
|
||||
from cic_eth.eth.rpc import RpcClient
|
||||
|
||||
celery_app = celery.current_app
|
||||
#logg = celery_app.log.get_default_logger()
|
||||
logg = logging.getLogger()
|
||||
|
||||
contract_function_signatures = {
|
||||
'convert': 'f3898a97',
|
||||
'convert2': '569706eb',
|
||||
}
|
||||
|
||||
|
||||
class BancorTxFactory(TxFactory):
|
||||
|
||||
"""Factory for creating Bancor network transactions.
|
||||
"""
|
||||
def convert(
|
||||
self,
|
||||
source_token_address,
|
||||
destination_token_address,
|
||||
reserve_address,
|
||||
source_amount,
|
||||
minimum_return,
|
||||
chain_spec,
|
||||
fee_beneficiary='0x0000000000000000000000000000000000000000',
|
||||
fee_ppm=0,
|
||||
):
|
||||
"""Create a BancorNetwork "convert" transaction.
|
||||
|
||||
:param source_token_address: ERC20 contract address for token to convert from
|
||||
:type source_token_address: str, 0x-hex
|
||||
:param destination_token_address: ERC20 contract address for token to convert to
|
||||
:type destination_token_address: str, 0x-hex
|
||||
:param reserve_address: ERC20 contract address of Common reserve token
|
||||
:type reserve_address: str, 0x-hex
|
||||
:param source_amount: Amount of source tokens to convert
|
||||
:type source_amount: int
|
||||
:param minimum_return: Minimum amount of destination tokens to accept as result for conversion
|
||||
:type source_amount: int
|
||||
:return: Unsigned "convert" transaction in standard Ethereum format
|
||||
:rtype: dict
|
||||
"""
|
||||
network_contract = CICRegistry.get_contract(chain_spec, 'BancorNetwork')
|
||||
network_gas = network_contract.gas('convert')
|
||||
tx_convert_buildable = network_contract.contract.functions.convert2(
|
||||
[
|
||||
source_token_address,
|
||||
source_token_address,
|
||||
reserve_address,
|
||||
destination_token_address,
|
||||
destination_token_address,
|
||||
],
|
||||
source_amount,
|
||||
minimum_return,
|
||||
fee_beneficiary,
|
||||
fee_ppm,
|
||||
)
|
||||
tx_convert = tx_convert_buildable.buildTransaction({
|
||||
'from': self.address,
|
||||
'gas': network_gas,
|
||||
'gasPrice': self.gas_price,
|
||||
'chainId': chain_spec.chain_id(),
|
||||
'nonce': self.next_nonce(),
|
||||
})
|
||||
return tx_convert
|
||||
|
||||
|
||||
def unpack_convert(data):
|
||||
f = data[2:10]
|
||||
if f != contract_function_signatures['convert2']:
|
||||
raise ValueError('Invalid convert data ({})'.format(f))
|
||||
|
||||
d = data[10:]
|
||||
path = d[384:]
|
||||
source = path[64-40:64]
|
||||
destination = path[-40:]
|
||||
|
||||
amount = int(d[64:128], 16)
|
||||
min_return = int(d[128:192], 16)
|
||||
fee_recipient = d[192:256]
|
||||
fee = int(d[256:320], 16)
|
||||
return {
|
||||
'amount': amount,
|
||||
'min_return': min_return,
|
||||
'source_token': web3.Web3.toChecksumAddress('0x' + source),
|
||||
'destination_token': web3.Web3.toChecksumAddress('0x' + destination),
|
||||
'fee_recipient': fee_recipient,
|
||||
'fee': fee,
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Kept for historical reference, it unpacks a convert call without fee parameters
|
||||
#def _unpack_convert_mint(data):
|
||||
# f = data[2:10]
|
||||
# if f != contract_function_signatures['convert2']:
|
||||
# raise ValueError('Invalid convert data ({})'.format(f))
|
||||
#
|
||||
# d = data[10:]
|
||||
# path = d[256:]
|
||||
# source = path[64-40:64]
|
||||
# destination = path[-40:]
|
||||
#
|
||||
# amount = int(d[64:128], 16)
|
||||
# min_return = int(d[128:192], 16)
|
||||
# return {
|
||||
# 'amount': amount,
|
||||
# 'min_return': min_return,
|
||||
# 'source_token': web3.Web3.toChecksumAddress('0x' + source),
|
||||
# 'destination_token': web3.Web3.toChecksumAddress('0x' + destination),
|
||||
# }
|
||||
|
||||
|
||||
@celery_app.task(bind=True)
|
||||
def convert_with_default_reserve(self, tokens, from_address, source_amount, minimum_return, to_address, chain_str):
|
||||
"""Performs a conversion between two liquid tokens using Bancor network.
|
||||
|
||||
:param tokens: Token pair, source and destination respectively
|
||||
:type tokens: list of str, 0x-hex
|
||||
:param from_address: Ethereum address of sender
|
||||
:type from_address: str, 0x-hex
|
||||
:param source_amount: Amount of source tokens to convert
|
||||
:type source_amount: int
|
||||
:param minimum_return: Minimum about of destination tokens to receive
|
||||
:type minimum_return: int
|
||||
"""
|
||||
|
||||
chain_spec = ChainSpec.from_chain_str(chain_str)
|
||||
queue = self.request.delivery_info['routing_key']
|
||||
|
||||
c = RpcClient(chain_spec, holder_address=from_address)
|
||||
|
||||
cr = CICRegistry.get_contract(chain_spec, 'BancorNetwork')
|
||||
source_token = CICRegistry.get_address(chain_spec, tokens[0]['address'])
|
||||
reserve_address = CICRegistry.get_contract(chain_spec, 'BNTToken', 'ERC20').address()
|
||||
|
||||
tx_factory = TokenTxFactory(from_address, c)
|
||||
|
||||
tx_approve_zero = tx_factory.approve(source_token.address(), cr.address(), 0, chain_spec)
|
||||
(tx_approve_zero_hash_hex, tx_approve_zero_signed_hex) = sign_and_register_tx(tx_approve_zero, chain_str, queue, 'cic_eth.eth.token.otx_cache_approve')
|
||||
|
||||
tx_approve = tx_factory.approve(source_token.address(), cr.address(), source_amount, chain_spec)
|
||||
(tx_approve_hash_hex, tx_approve_signed_hex) = sign_and_register_tx(tx_approve, chain_str, queue, 'cic_eth.eth.token.otx_cache_approve')
|
||||
|
||||
tx_factory = BancorTxFactory(from_address, c)
|
||||
tx_convert = tx_factory.convert(
|
||||
tokens[0]['address'],
|
||||
tokens[1]['address'],
|
||||
reserve_address,
|
||||
source_amount,
|
||||
minimum_return,
|
||||
chain_spec,
|
||||
)
|
||||
(tx_convert_hash_hex, tx_convert_signed_hex) = sign_and_register_tx(tx_convert, chain_str, queue, 'cic_eth.eth.bancor.otx_cache_convert')
|
||||
|
||||
# TODO: consider moving save recipient to async task / chain it before the tx send
|
||||
if to_address != None:
|
||||
save_convert_recipient(tx_convert_hash_hex, to_address, chain_str)
|
||||
|
||||
s = create_check_gas_and_send_task(
|
||||
[tx_approve_zero_signed_hex, tx_approve_signed_hex, tx_convert_signed_hex],
|
||||
chain_str,
|
||||
from_address,
|
||||
tx_approve_zero['gasPrice'] * tx_approve_zero['gas'],
|
||||
tx_hashes_hex=[tx_approve_hash_hex],
|
||||
queue=queue,
|
||||
)
|
||||
s.apply_async()
|
||||
return tx_convert_hash_hex
|
||||
|
||||
|
||||
#@celery_app.task()
|
||||
#def process_approval(tx_hash_hex):
|
||||
# t = session.query(TxConvertTransfer).query(TxConvertTransfer.approve_tx_hash==tx_hash_hex).first()
|
||||
# c = session.query(Otx).query(Otx.tx_hash==t.convert_tx_hash)
|
||||
# gas_limit = 8000000
|
||||
# gas_price = GasOracle.gas_price()
|
||||
#
|
||||
# # TODO: use celery group instead
|
||||
# s_queue = celery.signature(
|
||||
# 'cic_eth.queue.tx.create',
|
||||
# [
|
||||
# nonce,
|
||||
# c['address'], # TODO: check that this is in fact sender address
|
||||
# c['tx_hash'],
|
||||
# c['signed_tx'],
|
||||
# ]
|
||||
# )
|
||||
# s_queue.apply_async()
|
||||
#
|
||||
# s_check_gas = celery.signature(
|
||||
# 'cic_eth.eth.gas.check_gas',
|
||||
# [
|
||||
# c['address'],
|
||||
# [c['signed_tx']],
|
||||
# gas_limit * gas_price,
|
||||
# ]
|
||||
# )
|
||||
# s_send = celery.signature(
|
||||
# 'cic_eth.eth.tx.send',
|
||||
# [],
|
||||
# )
|
||||
#
|
||||
# s_set_sent = celery.signature(
|
||||
# 'cic_eth.queue.state.set_sent',
|
||||
# [False],
|
||||
# )
|
||||
# s_send.link(s_set_sent)
|
||||
# s_check_gas.link(s_send)
|
||||
# s_check_gas.apply_async()
|
||||
# return tx_hash_hex
|
||||
|
||||
|
||||
|
||||
@celery_app.task()
|
||||
def save_convert_recipient(convert_hash, recipient_address, chain_str):
|
||||
"""Registers the recipient target for a convert-and-transfer operation.
|
||||
|
||||
:param convert_hash: Transaction hash of convert operation
|
||||
:type convert_hash: str, 0x-hex
|
||||
:param recipient_address: Address of consequtive transfer recipient
|
||||
:type recipient_address: str, 0x-hex
|
||||
"""
|
||||
session = SessionBase.create_session()
|
||||
t = TxConvertTransfer(convert_hash, recipient_address, chain_str)
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
|
||||
@celery_app.task()
|
||||
def save_convert_transfer(convert_hash, transfer_hash):
|
||||
"""Registers that the transfer part of a convert-and-transfer operation has been executed.
|
||||
|
||||
:param convert_hash: Transaction hash of convert operation
|
||||
:type convert_hash: str, 0x-hex
|
||||
:param convert_hash: Transaction hash of transfer operation
|
||||
:type convert_hash: str, 0x-hex
|
||||
:returns: transfer_hash,
|
||||
:rtype: list, single str, 0x-hex
|
||||
"""
|
||||
session = SessionBase.create_session()
|
||||
t = TxConvertTransfer.get(convert_hash)
|
||||
t.transfer(transfer_hash)
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.close()
|
||||
return [transfer_hash]
|
||||
|
||||
|
||||
# TODO: seems unused, consider removing
|
||||
@celery_app.task()
|
||||
def resolve_converters_by_tokens(tokens, chain_str):
|
||||
"""Return converters for a list of tokens.
|
||||
|
||||
:param tokens: Token addresses to look up
|
||||
:type tokens: list of str, 0x-hex
|
||||
:return: Addresses of matching converters
|
||||
:rtype: list of str, 0x-hex
|
||||
"""
|
||||
chain_spec = ChainSpec.from_chain_str(chain_str)
|
||||
for t in tokens:
|
||||
c = CICRegistry.get_contract(chain_spec, 'ConverterRegistry')
|
||||
fn = c.function('getConvertersByAnchors')
|
||||
try:
|
||||
converters = fn([t['address']]).call()
|
||||
except Exception as e:
|
||||
raise e
|
||||
t['converters'] = converters
|
||||
|
||||
return tokens
|
||||
|
||||
|
||||
@celery_app.task(bind=True)
|
||||
def transfer_converted(self, tokens, holder_address, receiver_address, value, tx_convert_hash_hex, chain_str):
|
||||
"""Execute the ERC20 transfer of a convert-and-transfer operation.
|
||||
|
||||
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 holder_address: Token receiver address
|
||||
:type holder_address: str, 0x-hex
|
||||
:param value: Amount of token, in 'wei'
|
||||
:type value: int
|
||||
:raises TokenCountError: Either none or more then one tokens have been passed as tokens argument
|
||||
:return: Transaction hash
|
||||
:rtype: str, 0x-hex
|
||||
"""
|
||||
# we only allow one token, one transfer
|
||||
if len(tokens) != 1:
|
||||
raise TokenCountError
|
||||
|
||||
chain_spec = ChainSpec.from_chain_str(chain_str)
|
||||
|
||||
queue = self.request.delivery_info['routing_key']
|
||||
|
||||
c = RpcClient(chain_spec, holder_address=holder_address)
|
||||
|
||||
# get transaction parameters
|
||||
gas_price = c.gas_price()
|
||||
tx_factory = TokenTxFactory(holder_address, c)
|
||||
|
||||
token_address = tokens[0]['address']
|
||||
tx_transfer = tx_factory.transfer(
|
||||
token_address,
|
||||
receiver_address,
|
||||
value,
|
||||
chain_spec,
|
||||
)
|
||||
(tx_transfer_hash_hex, tx_transfer_signed_hex) = sign_and_register_tx(tx_transfer, chain_str, queue, 'cic_eth.eth.token.otx_cache_transfer')
|
||||
|
||||
# send transaction
|
||||
logg.info('transfer converted token {} from {} to {} value {} {}'.format(token_address, holder_address, receiver_address, value, tx_transfer_signed_hex))
|
||||
s = create_check_gas_and_send_task(
|
||||
[tx_transfer_signed_hex],
|
||||
chain_str,
|
||||
holder_address,
|
||||
tx_transfer['gasPrice'] * tx_transfer['gas'],
|
||||
None,
|
||||
queue,
|
||||
)
|
||||
s_save = celery.signature(
|
||||
'cic_eth.eth.bancor.save_convert_transfer',
|
||||
[
|
||||
tx_convert_hash_hex,
|
||||
tx_transfer_hash_hex,
|
||||
],
|
||||
queue=queue,
|
||||
)
|
||||
s_save.link(s)
|
||||
s_save.apply_async()
|
||||
return tx_transfer_hash_hex
|
||||
|
||||
|
||||
@celery_app.task()
|
||||
def otx_cache_convert(
|
||||
tx_hash_hex,
|
||||
tx_signed_raw_hex,
|
||||
chain_str,
|
||||
):
|
||||
|
||||
chain_spec = ChainSpec.from_chain_str(chain_str)
|
||||
tx_signed_raw_bytes = bytes.fromhex(tx_signed_raw_hex[2:])
|
||||
tx = unpack(tx_signed_raw_bytes, chain_spec)
|
||||
tx_data = unpack_convert(tx['data'])
|
||||
logg.debug('tx data {}'.format(tx_data))
|
||||
|
||||
session = TxCache.create_session()
|
||||
tx_cache = TxCache(
|
||||
tx_hash_hex,
|
||||
tx['from'],
|
||||
tx['from'],
|
||||
tx_data['source_token'],
|
||||
tx_data['destination_token'],
|
||||
tx_data['amount'],
|
||||
tx_data['amount'],
|
||||
)
|
||||
session.add(tx_cache)
|
||||
session.commit()
|
||||
session.close()
|
||||
return tx_hash_hex
|
||||
|
||||
@@ -13,9 +13,9 @@ from chainlib.eth.tx import (
|
||||
from cic_eth_registry import CICRegistry
|
||||
from cic_eth_registry.erc20 import ERC20Token
|
||||
from hexathon import strip_0x
|
||||
from chainqueue.db.models.tx import TxCache
|
||||
from chainqueue.error import NotLocalTxError
|
||||
from eth_erc20 import ERC20
|
||||
from chainqueue.sql.tx import cache_tx_dict
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.base import SessionBase
|
||||
@@ -375,19 +375,16 @@ def cache_transfer_data(
|
||||
token_value = tx_data[1]
|
||||
|
||||
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
|
||||
tx_dict = {
|
||||
'hash': tx_hash_hex,
|
||||
'from': tx['from'],
|
||||
'to': recipient_address,
|
||||
'source_token': tx['to'],
|
||||
'destination_token': tx['to'],
|
||||
'from_value': token_value,
|
||||
'to_value': token_value,
|
||||
}
|
||||
(tx_dict, cache_id) = cache_tx_dict(tx_dict, session=session)
|
||||
session.close()
|
||||
return (tx_hash_hex, cache_id)
|
||||
|
||||
@@ -417,19 +414,16 @@ def cache_transfer_from_data(
|
||||
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
|
||||
tx_dict = {
|
||||
'hash': tx_hash_hex,
|
||||
'from': tx['from'],
|
||||
'to': recipient_address,
|
||||
'source_token': tx['to'],
|
||||
'destination_token': tx['to'],
|
||||
'from_value': token_value,
|
||||
'to_value': token_value,
|
||||
}
|
||||
(tx_dict, cache_id) = cache_tx_dict(tx_dict, session=session)
|
||||
session.close()
|
||||
return (tx_hash_hex, cache_id)
|
||||
|
||||
@@ -458,19 +452,16 @@ def cache_approve_data(
|
||||
token_value = tx_data[1]
|
||||
|
||||
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
|
||||
tx_dict = {
|
||||
'hash': tx_hash_hex,
|
||||
'from': tx['from'],
|
||||
'to': recipient_address,
|
||||
'source_token': tx['to'],
|
||||
'destination_token': tx['to'],
|
||||
'from_value': token_value,
|
||||
'to_value': token_value,
|
||||
}
|
||||
(tx_dict, cache_id) = cache_tx_dict(tx_dict, session=session)
|
||||
session.close()
|
||||
return (tx_hash_hex, cache_id)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.address import is_checksum_address
|
||||
from chainlib.connection import RPCConnection
|
||||
from chainqueue.db.enum import StatusBits
|
||||
from chainqueue.sql.tx import cache_tx_dict
|
||||
from chainlib.eth.gas import (
|
||||
balance,
|
||||
price,
|
||||
@@ -133,20 +134,17 @@ def cache_gas_data(
|
||||
|
||||
session = SessionBase.create_session()
|
||||
|
||||
tx_cache = TxCache(
|
||||
tx_hash_hex,
|
||||
tx['from'],
|
||||
tx['to'],
|
||||
ZERO_ADDRESS,
|
||||
ZERO_ADDRESS,
|
||||
tx['value'],
|
||||
tx['value'],
|
||||
session=session,
|
||||
)
|
||||
tx_dict = {
|
||||
'hash': tx_hash_hex,
|
||||
'from': tx['from'],
|
||||
'to': tx['to'],
|
||||
'source_token': ZERO_ADDRESS,
|
||||
'destination_token': ZERO_ADDRESS,
|
||||
'from_value': tx['value'],
|
||||
'to_value': tx['value'],
|
||||
}
|
||||
|
||||
session.add(tx_cache)
|
||||
session.commit()
|
||||
cache_id = tx_cache.id
|
||||
(tx_dict, cache_id) = cache_tx_dict(tx_dict, session=session)
|
||||
session.close()
|
||||
return (tx_hash_hex, cache_id)
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ from hexathon import (
|
||||
strip_0x,
|
||||
)
|
||||
from chainqueue.db.models.tx import Otx
|
||||
from chainqueue.db.models.tx import TxCache
|
||||
from chainqueue.db.enum import StatusBits
|
||||
from chainqueue.error import NotLocalTxError
|
||||
from potaahto.symbols import snake_and_camel
|
||||
|
||||
@@ -14,9 +14,11 @@ from chainlib.eth.tx import (
|
||||
)
|
||||
from chainlib.eth.block import block_by_number
|
||||
from chainlib.eth.contract import abi_decode_single
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from hexathon import strip_0x
|
||||
from cic_eth_registry import CICRegistry
|
||||
from cic_eth_registry.erc20 import ERC20Token
|
||||
from cic_eth_registry.error import UnknownContractError
|
||||
from chainqueue.db.models.otx import Otx
|
||||
from chainqueue.db.enum import StatusEnum
|
||||
from chainqueue.sql.query import get_tx_cache
|
||||
@@ -114,9 +116,6 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict):
|
||||
|
||||
# TODO: pass through registry to validate declarator entry of token
|
||||
#token = registry.by_address(tx['to'], sender_address=self.call_address)
|
||||
token = ERC20Token(chain_spec, rpc, tx['to'])
|
||||
token_symbol = token.symbol
|
||||
token_decimals = token.decimals
|
||||
times = tx_times(tx['hash'], chain_spec)
|
||||
tx_r = {
|
||||
'hash': tx['hash'],
|
||||
@@ -126,12 +125,6 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict):
|
||||
'destination_value': tx_token_value,
|
||||
'source_token': tx['to'],
|
||||
'destination_token': tx['to'],
|
||||
'source_token_symbol': token_symbol,
|
||||
'destination_token_symbol': token_symbol,
|
||||
'source_token_decimals': token_decimals,
|
||||
'destination_token_decimals': token_decimals,
|
||||
'source_token_chain': chain_str,
|
||||
'destination_token_chain': chain_str,
|
||||
'nonce': tx['nonce'],
|
||||
}
|
||||
if times['queue'] != None:
|
||||
@@ -146,8 +139,8 @@ def list_tx_by_bloom(self, bloomspec, address, chain_spec_dict):
|
||||
# TODO: Surely it must be possible to optimize this
|
||||
# TODO: DRY this with callback filter in cic_eth/runnable/manager
|
||||
# TODO: Remove redundant fields from end representation (timestamp, tx_hash)
|
||||
@celery_app.task()
|
||||
def tx_collate(tx_batches, chain_spec_dict, offset, limit, newest_first=True):
|
||||
@celery_app.task(bind=True, base=BaseTask)
|
||||
def tx_collate(self, tx_batches, chain_spec_dict, offset, limit, newest_first=True, verify_contracts=True):
|
||||
"""Merges transaction data from multiple sources and sorts them in chronological order.
|
||||
|
||||
:param tx_batches: Transaction data inputs
|
||||
@@ -196,6 +189,32 @@ def tx_collate(tx_batches, chain_spec_dict, offset, limit, newest_first=True):
|
||||
if newest_first:
|
||||
ks.reverse()
|
||||
for k in ks:
|
||||
txs.append(txs_by_block[k])
|
||||
tx = txs_by_block[k]
|
||||
if verify_contracts:
|
||||
try:
|
||||
tx = verify_and_expand(tx, chain_spec, sender_address=BaseTask.call_address)
|
||||
except UnknownContractError:
|
||||
logg.error('verify failed on tx {}, skipping'.format(tx['hash']))
|
||||
continue
|
||||
txs.append(tx)
|
||||
|
||||
return txs
|
||||
|
||||
|
||||
def verify_and_expand(tx, chain_spec, sender_address=ZERO_ADDRESS):
|
||||
rpc = RPCConnection.connect(chain_spec, 'default')
|
||||
registry = CICRegistry(chain_spec, rpc)
|
||||
|
||||
if tx.get('source_token_symbol') == None and tx['source_token'] != ZERO_ADDRESS:
|
||||
r = registry.by_address(tx['source_token'], sender_address=sender_address)
|
||||
token = ERC20Token(chain_spec, rpc, tx['source_token'])
|
||||
tx['source_token_symbol'] = token.symbol
|
||||
tx['source_token_decimals'] = token.decimals
|
||||
|
||||
if tx.get('destination_token_symbol') == None and tx['destination_token'] != ZERO_ADDRESS:
|
||||
r = registry.by_address(tx['destination_token'], sender_address=sender_address)
|
||||
token = ERC20Token(chain_spec, rpc, tx['destination_token'])
|
||||
tx['destination_token_symbol'] = token.symbol
|
||||
tx['destination_token_decimals'] = token.decimals
|
||||
|
||||
return tx
|
||||
|
||||
@@ -27,7 +27,7 @@ def database_engine(
|
||||
SessionBase.poolable = False
|
||||
dsn = dsn_from_config(load_config)
|
||||
#SessionBase.connect(dsn, True)
|
||||
SessionBase.connect(dsn, debug=load_config.get('DATABASE_DEBUG') != None)
|
||||
SessionBase.connect(dsn, debug=load_config.true('DATABASE_DEBUG'))
|
||||
return dsn
|
||||
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ def get_upcoming_tx(chain_spec, status=StatusEnum.READYSEND, not_status=None, re
|
||||
q_outer = q_outer.join(Lock, isouter=True)
|
||||
q_outer = q_outer.filter(or_(Lock.flags==None, Lock.flags.op('&')(LockEnum.SEND.value)==0))
|
||||
|
||||
|
||||
if not is_alive(status):
|
||||
SessionBase.release_session(session)
|
||||
raise ValueError('not a valid non-final tx value: {}'.format(status))
|
||||
|
||||
@@ -80,7 +80,12 @@ def main():
|
||||
t = api.create_account(register=register)
|
||||
|
||||
ps.get_message()
|
||||
o = ps.get_message(timeout=args.timeout)
|
||||
try:
|
||||
o = ps.get_message(timeout=args.timeout)
|
||||
except TimeoutError as e:
|
||||
sys.stderr.write('got no new address from cic-eth before timeout: {}\n'.format(e))
|
||||
sys.exit(1)
|
||||
ps.unsubscribe()
|
||||
m = json.loads(o['data'])
|
||||
print(m['result'])
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ class DispatchSyncer:
|
||||
|
||||
def __init__(self, chain_spec):
|
||||
self.chain_spec = chain_spec
|
||||
self.session = None
|
||||
|
||||
|
||||
def chain(self):
|
||||
@@ -100,16 +101,18 @@ class DispatchSyncer:
|
||||
c = len(txs.keys())
|
||||
logg.debug('processing {} txs {}'.format(c, list(txs.keys())))
|
||||
chain_str = str(self.chain_spec)
|
||||
session = SessionBase.create_session()
|
||||
self.session = SessionBase.create_session()
|
||||
for k in txs.keys():
|
||||
tx_raw = txs[k]
|
||||
tx_raw_bytes = bytes.fromhex(strip_0x(tx_raw))
|
||||
tx = unpack(tx_raw_bytes, self.chain_spec)
|
||||
|
||||
try:
|
||||
set_reserved(self.chain_spec, tx['hash'], session=session)
|
||||
set_reserved(self.chain_spec, tx['hash'], session=self.session)
|
||||
self.session.commit()
|
||||
except NotLocalTxError as e:
|
||||
logg.warning('dispatcher was triggered with non-local tx {}'.format(tx['hash']))
|
||||
self.session.rollback()
|
||||
continue
|
||||
|
||||
s_check = celery.signature(
|
||||
@@ -132,16 +135,25 @@ class DispatchSyncer:
|
||||
s_check.link(s_send)
|
||||
t = s_check.apply_async()
|
||||
logg.info('processed {}'.format(k))
|
||||
self.session.close()
|
||||
self.session = None
|
||||
|
||||
|
||||
def loop(self, w3, interval):
|
||||
def loop(self, interval):
|
||||
while run:
|
||||
txs = {}
|
||||
typ = StatusBits.QUEUED
|
||||
utxs = get_upcoming_tx(self.chain_spec, typ)
|
||||
for k in utxs.keys():
|
||||
txs[k] = utxs[k]
|
||||
self.process(w3, txs)
|
||||
try:
|
||||
conn = RPCConnection.connect(self.chain_spec, 'default')
|
||||
self.process(conn, txs)
|
||||
except ConnectionError as e:
|
||||
if self.session != None:
|
||||
self.session.close()
|
||||
self.session = None
|
||||
logg.error('connection to node failed: {}'.format(e))
|
||||
|
||||
if len(utxs) > 0:
|
||||
time.sleep(self.yield_delay)
|
||||
@@ -151,8 +163,7 @@ class DispatchSyncer:
|
||||
|
||||
def main():
|
||||
syncer = DispatchSyncer(chain_spec)
|
||||
conn = RPCConnection.connect(chain_spec, 'default')
|
||||
syncer.loop(conn, float(config.get('DISPATCHER_LOOP_INTERVAL')))
|
||||
syncer.loop(float(config.get('DISPATCHER_LOOP_INTERVAL')))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from chainqueue.db.enum import StatusBits
|
||||
from chainqueue.db.models.tx import TxCache
|
||||
from chainqueue.db.models.otx import Otx
|
||||
from chainqueue.sql.query import get_paused_tx_cache as get_paused_tx
|
||||
from chainlib.eth.address import to_checksum_address
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.base import SessionBase
|
||||
@@ -47,12 +48,13 @@ class GasFilter(SyncFilter):
|
||||
|
||||
SessionBase.release_session(session)
|
||||
|
||||
address = to_checksum_address(r[0])
|
||||
logg.info('resuming gas-in-waiting txs for {}'.format(r[0]))
|
||||
if len(txs) > 0:
|
||||
s = create_check_gas_task(
|
||||
list(txs.values()),
|
||||
self.chain_spec,
|
||||
r[0],
|
||||
address,
|
||||
0,
|
||||
tx_hashes_hex=list(txs.keys()),
|
||||
queue=self.queue,
|
||||
|
||||
@@ -9,8 +9,8 @@ import semver
|
||||
version = (
|
||||
0,
|
||||
12,
|
||||
0,
|
||||
'alpha.2',
|
||||
2,
|
||||
'alpha.3',
|
||||
)
|
||||
|
||||
version_object = semver.VersionInfo(
|
||||
|
||||
@@ -6,4 +6,4 @@ HOST=localhost
|
||||
PORT=5432
|
||||
ENGINE=sqlite
|
||||
DRIVER=pysqlite
|
||||
DEBUG=
|
||||
DEBUG=0
|
||||
|
||||
@@ -13,7 +13,7 @@ ARG GITLAB_PYTHON_REGISTRY="https://gitlab.com/api/v4/projects/27624814/packages
|
||||
# --force-reinstall \
|
||||
# --extra-index-url $GITLAB_PYTHON_REGISTRY --extra-index-url $EXTRA_INDEX_URL \
|
||||
# -r requirements.txt
|
||||
COPY *requirements.txt .
|
||||
COPY *requirements.txt ./
|
||||
RUN --mount=type=cache,mode=0755,target=/root/.cache/pip \
|
||||
pip install --index-url https://pypi.org/simple \
|
||||
--extra-index-url $GITLAB_PYTHON_REGISTRY \
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
celery==4.4.7
|
||||
chainlib~=0.0.5a1
|
||||
chainlib-eth>=0.0.6a1,<0.1.0
|
||||
semver==2.13.0
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
chainsyncer[sql]~=0.0.3a3
|
||||
chainqueue~=0.0.2b5
|
||||
chainqueue>=0.0.3a2,<0.1.0
|
||||
chainsyncer[sql]>=0.0.5a1,<0.1.0
|
||||
alembic==1.4.2
|
||||
confini~=0.3.6rc4
|
||||
confini>=0.3.6rc4,<0.5.0
|
||||
redis==3.5.3
|
||||
hexathon~=0.0.1a7
|
||||
pycryptodome==3.10.1
|
||||
liveness~=0.0.1a7
|
||||
eth-address-index~=0.1.2a1
|
||||
eth-accounts-index~=0.0.12a1
|
||||
cic-eth-registry~=0.5.6a1
|
||||
erc20-faucet~=0.2.2a1
|
||||
erc20-transfer-authorization~=0.3.2a1
|
||||
sarafu-faucet~=0.0.4a1
|
||||
eth-address-index>=0.1.3a1,<0.2.0
|
||||
eth-accounts-index>=0.0.13a1,<0.1.0
|
||||
cic-eth-registry>=0.5.7a1,<0.6.0
|
||||
erc20-faucet>=0.2.3a1,<0.3.0
|
||||
erc20-transfer-authorization>=0.3.3a1,<0.4.0
|
||||
sarafu-faucet>=0.0.4a5,<0.1.0
|
||||
moolb~=0.1.1b2
|
||||
erc20-transfer-authorization~=0.3.2a1
|
||||
|
||||
@@ -6,4 +6,4 @@ pytest-redis==2.0.0
|
||||
redis==3.5.3
|
||||
eth-tester==0.5.0b3
|
||||
py-evm==0.3.0a20
|
||||
eth-erc20~=0.0.10a2
|
||||
eth-erc20~=0.0.11a1
|
||||
|
||||
@@ -290,6 +290,7 @@ def test_fix_nonce(
|
||||
txs = get_nonce_tx_cache(default_chain_spec, 3, agent_roles['ALICE'], session=init_database)
|
||||
ks = txs.keys()
|
||||
assert len(ks) == 2
|
||||
|
||||
for k in ks:
|
||||
hsh = add_0x(k)
|
||||
otx = Otx.load(hsh, session=init_database)
|
||||
|
||||
@@ -184,7 +184,7 @@ def test_admin_api_account(
|
||||
|
||||
|
||||
api = AdminApi(eth_rpc, queue=None, call_address=contract_roles['CONTRACT_DEPLOYER'])
|
||||
r = api.account(default_chain_spec, agent_roles['ALICE'])
|
||||
r = api.account(default_chain_spec, agent_roles['ALICE'], include_sender=True, include_recipient=True)
|
||||
assert len(r) == 5
|
||||
|
||||
api = AdminApi(eth_rpc, queue=None, call_address=contract_roles['CONTRACT_DEPLOYER'])
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# external imports
|
||||
import celery
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import (
|
||||
receipt,
|
||||
@@ -20,6 +21,7 @@ def test_translate(
|
||||
cic_registry,
|
||||
init_celery_tasks,
|
||||
register_lookups,
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
nonce_oracle = RPCNonceOracle(contract_roles['CONTRACT_DEPLOYER'], eth_rpc)
|
||||
@@ -46,6 +48,20 @@ def test_translate(
|
||||
'recipient': agent_roles['BOB'],
|
||||
'recipient_label': None,
|
||||
}
|
||||
tx = translate_tx_addresses(tx, [contract_roles['CONTRACT_DEPLOYER']], default_chain_spec.asdict())
|
||||
assert tx['sender_label'] == 'alice'
|
||||
assert tx['recipient_label'] == 'bob'
|
||||
|
||||
#tx = translate_tx_addresses(tx, [contract_roles['CONTRACT_DEPLOYER']], default_chain_spec.asdict())
|
||||
s = celery.signature(
|
||||
'cic_eth.ext.address.translate_tx_addresses',
|
||||
[
|
||||
tx,
|
||||
[contract_roles['CONTRACT_DEPLOYER']],
|
||||
default_chain_spec.asdict(),
|
||||
],
|
||||
queue=None,
|
||||
)
|
||||
t = s.apply_async()
|
||||
r = t.get_leaf()
|
||||
assert t.successful()
|
||||
|
||||
assert r['sender_label'] == 'alice'
|
||||
assert r['recipient_label'] == 'bob'
|
||||
92
apps/cic-eth/tests/task/test_task_list.py
Normal file
92
apps/cic-eth/tests/task/test_task_list.py
Normal file
@@ -0,0 +1,92 @@
|
||||
# external imports
|
||||
import celery
|
||||
import pytest
|
||||
from chainlib.connection import RPCConnection
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.gas import (
|
||||
RPCGasOracle,
|
||||
)
|
||||
from chainlib.eth.tx import (
|
||||
TxFormat,
|
||||
unpack,
|
||||
)
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from eth_erc20 import ERC20
|
||||
from hexathon import (
|
||||
add_0x,
|
||||
strip_0x,
|
||||
)
|
||||
from chainqueue.db.models.tx import TxCache
|
||||
from chainqueue.db.models.otx import Otx
|
||||
|
||||
|
||||
def test_ext_tx_collate(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
eth_rpc,
|
||||
eth_signer,
|
||||
custodial_roles,
|
||||
agent_roles,
|
||||
foo_token,
|
||||
bar_token,
|
||||
register_tokens,
|
||||
cic_registry,
|
||||
register_lookups,
|
||||
init_celery_tasks,
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
rpc = RPCConnection.connect(default_chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(custodial_roles['FOO_TOKEN_GIFTER'], eth_rpc)
|
||||
gas_oracle = RPCGasOracle(eth_rpc)
|
||||
|
||||
c = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
transfer_value_foo = 1000
|
||||
transfer_value_bar = 1024
|
||||
(tx_hash_hex, tx_signed_raw_hex) = c.transfer(foo_token, custodial_roles['FOO_TOKEN_GIFTER'], agent_roles['ALICE'], transfer_value_foo, tx_format=TxFormat.RLP_SIGNED)
|
||||
tx = unpack(bytes.fromhex(strip_0x(tx_signed_raw_hex)), default_chain_spec)
|
||||
|
||||
otx = Otx(
|
||||
tx['nonce'],
|
||||
tx_hash_hex,
|
||||
tx_signed_raw_hex,
|
||||
)
|
||||
init_database.add(otx)
|
||||
init_database.commit()
|
||||
|
||||
txc = TxCache(
|
||||
tx_hash_hex,
|
||||
tx['from'],
|
||||
tx['to'],
|
||||
foo_token,
|
||||
bar_token,
|
||||
transfer_value_foo,
|
||||
transfer_value_bar,
|
||||
666,
|
||||
13,
|
||||
session=init_database,
|
||||
)
|
||||
init_database.add(txc)
|
||||
init_database.commit()
|
||||
|
||||
s = celery.signature(
|
||||
'cic_eth.ext.tx.tx_collate',
|
||||
[
|
||||
{tx_hash_hex: tx_signed_raw_hex},
|
||||
default_chain_spec.asdict(),
|
||||
0,
|
||||
100,
|
||||
],
|
||||
queue=None,
|
||||
)
|
||||
t = s.apply_async()
|
||||
r = t.get_leaf()
|
||||
assert t.successful()
|
||||
|
||||
assert len(r) == 1
|
||||
|
||||
tx = r[0]
|
||||
assert tx['source_token_symbol'] == 'FOO'
|
||||
assert tx['source_token_decimals'] == 6
|
||||
assert tx['destination_token_symbol'] == 'BAR'
|
||||
assert tx['destination_token_decimals'] == 9
|
||||
@@ -1,6 +1,7 @@
|
||||
# third-party imports
|
||||
# extended imports
|
||||
import pytest
|
||||
import uuid
|
||||
import unittest
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.nonce import (
|
||||
@@ -55,7 +56,7 @@ def test_nonce_reserve(
|
||||
o = q.first()
|
||||
assert o.nonce == 43
|
||||
|
||||
nonce = NonceReservation.release(eth_empty_accounts[0], str(uu))
|
||||
nonce = NonceReservation.release(eth_empty_accounts[0], str(uu), session=init_database)
|
||||
init_database.commit()
|
||||
assert nonce == (str(uu), 42)
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@ from chainlib.eth.gas import (
|
||||
Gas,
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
from hexathon import (
|
||||
add_0x,
|
||||
strip_0x,
|
||||
uniform as hex_uniform,
|
||||
)
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.enum import LockEnum
|
||||
@@ -34,7 +39,10 @@ def test_upcoming_with_lock(
|
||||
gas_oracle = RPCGasOracle(eth_rpc)
|
||||
c = Gas(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
|
||||
(tx_hash_hex, tx_rpc) = c.create(agent_roles['ALICE'], agent_roles['BOB'], 100 * (10 ** 6))
|
||||
alice_normal = add_0x(hex_uniform(strip_0x(agent_roles['ALICE'])))
|
||||
bob_normal = add_0x(hex_uniform(strip_0x(agent_roles['BOB'])))
|
||||
|
||||
(tx_hash_hex, tx_rpc) = c.create(alice_normal, bob_normal, 100 * (10 ** 6))
|
||||
tx_signed_raw_hex = tx_rpc['params'][0]
|
||||
|
||||
register_tx(tx_hash_hex, tx_signed_raw_hex, default_chain_spec, None, session=init_database)
|
||||
@@ -43,12 +51,12 @@ def test_upcoming_with_lock(
|
||||
txs = get_upcoming_tx(default_chain_spec, StatusEnum.PENDING)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
Lock.set(str(default_chain_spec), LockEnum.SEND, address=agent_roles['ALICE'])
|
||||
Lock.set(str(default_chain_spec), LockEnum.SEND, address=alice_normal)
|
||||
|
||||
txs = get_upcoming_tx(default_chain_spec, StatusEnum.PENDING)
|
||||
txs = get_upcoming_tx(default_chain_spec, status=StatusEnum.PENDING)
|
||||
assert len(txs.keys()) == 0
|
||||
|
||||
(tx_hash_hex, tx_rpc) = c.create(agent_roles['BOB'], agent_roles['ALICE'], 100 * (10 ** 6))
|
||||
(tx_hash_hex, tx_rpc) = c.create(bob_normal, alice_normal, 100 * (10 ** 6))
|
||||
tx_signed_raw_hex = tx_rpc['params'][0]
|
||||
|
||||
register_tx(tx_hash_hex, tx_signed_raw_hex, default_chain_spec, None, session=init_database)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
crypto-dev-signer~=0.4.14b6
|
||||
chainqueue~=0.0.2b5
|
||||
confini~=0.3.6rc4
|
||||
cic-eth-registry~=0.5.6a1
|
||||
crypto-dev-signer>=0.4.14b7,<=0.4.14
|
||||
chainqueue~=0.0.2b6
|
||||
confini>=0.3.6rc4,<0.5.0
|
||||
cic-eth-registry>=0.5.7a1,<0.6.0
|
||||
redis==3.5.3
|
||||
hexathon~=0.0.1a7
|
||||
pycryptodome==3.10.1
|
||||
|
||||
@@ -9,7 +9,7 @@ import semver
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
version = (0, 4, 0, 'alpha.7')
|
||||
version = (0, 4, 0, 'alpha.10')
|
||||
|
||||
version_object = semver.VersionInfo(
|
||||
major=version[0],
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
cic_base[full_graph]==0.1.3a3+build.984b5cff
|
||||
confini~=0.4.1a1
|
||||
africastalking==1.2.3
|
||||
SQLAlchemy==1.3.20
|
||||
alembic==1.4.2
|
||||
psycopg2==2.8.6
|
||||
celery==4.4.7
|
||||
redis==3.5.3
|
||||
|
||||
@@ -2,3 +2,4 @@ pytest~=6.0.1
|
||||
pytest-celery~=0.0.0a1
|
||||
pytest-mock~=3.3.1
|
||||
pysqlite3~=0.4.3
|
||||
pytest-cov==2.10.1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[app]
|
||||
ALLOWED_IP=0.0.0.0/0
|
||||
LOCALE_FALLBACK=en
|
||||
LOCALE_PATH=/usr/src/cic-ussd/var/lib/locale/
|
||||
LOCALE_PATH=var/lib/locale/
|
||||
MAX_BODY_LENGTH=1024
|
||||
PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I=
|
||||
SERVICE_CODE=*483*46#,*483*061#,*384*96#
|
||||
@@ -11,13 +11,13 @@ SUPPORT_PHONE_NUMBER=0757628885
|
||||
REGION=KE
|
||||
|
||||
[ussd]
|
||||
MENU_FILE=/usr/src/data/ussd_menu.json
|
||||
MENU_FILE=data/ussd_menu.json
|
||||
user =
|
||||
pass =
|
||||
|
||||
[statemachine]
|
||||
STATES=/usr/src/cic-ussd/states/
|
||||
TRANSITIONS=/usr/src/cic-ussd/transitions/
|
||||
STATES=states/
|
||||
TRANSITIONS=transitions/
|
||||
|
||||
[client]
|
||||
host =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[pgp]
|
||||
export_dir = /usr/src/pgp/keys/
|
||||
export_dir = pgp/keys/
|
||||
keys_path = /usr/src/secrets/
|
||||
private_keys = privatekeys_meta.asc
|
||||
passphrase =
|
||||
|
||||
@@ -127,3 +127,4 @@ class SessionBase(Model):
|
||||
logg.debug('commit and destroy session {}'.format(session_key))
|
||||
session.commit()
|
||||
session.close()
|
||||
del SessionBase.localsessions[session_key]
|
||||
|
||||
@@ -28,7 +28,7 @@ elif args.v:
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
# parse config
|
||||
config = Config(config_dir=args.c, env_prefix=args.env_prefix)
|
||||
config = Config(args.c, env_prefix=args.env_prefix)
|
||||
config.process()
|
||||
config.censor('PASSWORD', 'DATABASE')
|
||||
logg.debug('config loaded from {}:\n{}'.format(args.c, config))
|
||||
|
||||
@@ -45,7 +45,7 @@ elif args.v:
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
# parse config
|
||||
config = Config(config_dir=args.c, env_prefix=args.env_prefix)
|
||||
config = Config(args.c, env_prefix=args.env_prefix)
|
||||
config.process()
|
||||
config.censor('PASSWORD', 'DATABASE')
|
||||
logg.debug('config loaded from {}:\n{}'.format(args.c, config))
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
user_server_port=${SERVER_PORT:-9500}
|
||||
|
||||
/usr/local/bin/uwsgi --wsgi-file /usr/local/lib/python3.8/site-packages/cic_ussd/runnable/daemons/cic_user_server.py --http :"$user_server_port" --pyargv "$@"
|
||||
/usr/local/bin/uwsgi --wsgi-file cic_ussd/runnable/daemons/cic_user_server.py --http :"$user_server_port" --pyargv "$@"
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
user_ussd_server_port=${SERVER_PORT:-9000}
|
||||
|
||||
/usr/local/bin/uwsgi --wsgi-file /usr/local/lib/python3.8/site-packages/cic_ussd/runnable/daemons/cic_user_ussd_server.py --http :"$user_ussd_server_port" --pyargv "$@"
|
||||
/usr/local/bin/uwsgi --wsgi-file cic_ussd/runnable/daemons/cic_user_ussd_server.py --http :"$user_ussd_server_port" --pyargv "$@"
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
cic_base[full_graph]==0.1.3a3+build.984b5cff
|
||||
cic-eth~=0.12.0a1
|
||||
cic-notify~=0.4.0a7
|
||||
cic-types~=0.1.0a11
|
||||
cic-eth~=0.12.2a3
|
||||
cic-notify~=0.4.0a10
|
||||
cic-types~=0.1.0a14
|
||||
confini~=0.4.1a1
|
||||
semver==2.13.0
|
||||
alembic==1.4.2
|
||||
SQLAlchemy==1.3.20
|
||||
psycopg2==2.8.6
|
||||
tinydb==4.2.0
|
||||
phonenumbers==8.12.12
|
||||
redis==3.5.3
|
||||
celery==4.4.7
|
||||
python-i18n==0.3.9
|
||||
pyxdg==0.27
|
||||
bcrypt==3.2.0
|
||||
uWSGI==2.0.19.1
|
||||
transitions==0.8.4
|
||||
|
||||
@@ -30,7 +30,7 @@ arg_parser.add_argument('-vv', action='store_true', help='be more verbose')
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
|
||||
config = Config(config_dir=args.c, env_prefix=args.env_prefix)
|
||||
config = Config(args.c, env_prefix=args.env_prefix)
|
||||
config.process()
|
||||
config.censor('PASSWORD', 'DATABASE')
|
||||
logg.debug(f'config:\n{config}')
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[bancor]
|
||||
dir = /usr/local/share/cic/bancor
|
||||
2
apps/contract-migration/config_template/chain.ini
Normal file
2
apps/contract-migration/config_template/chain.ini
Normal file
@@ -0,0 +1,2 @@
|
||||
[chain]
|
||||
spec = evm:ethereum:1
|
||||
4
apps/contract-migration/config_template/redis.ini
Normal file
4
apps/contract-migration/config_template/redis.ini
Normal file
@@ -0,0 +1,4 @@
|
||||
[redis]
|
||||
host = localhost
|
||||
port = 63379
|
||||
db = 0
|
||||
5
apps/contract-migration/config_template/rpc.ini
Normal file
5
apps/contract-migration/config_template/rpc.ini
Normal file
@@ -0,0 +1,5 @@
|
||||
[rpc]
|
||||
http_provider = http://localhost:8545
|
||||
http_authentication =
|
||||
http_username =
|
||||
http_password =
|
||||
8
apps/contract-migration/config_template/token.ini
Normal file
8
apps/contract-migration/config_template/token.ini
Normal file
@@ -0,0 +1,8 @@
|
||||
[token]
|
||||
name =
|
||||
symbol =
|
||||
decimals =
|
||||
demurrage_level =
|
||||
redistribution_period =
|
||||
sink_address =
|
||||
supply_limit = 0
|
||||
3
apps/contract-migration/config_template/wallet.ini
Normal file
3
apps/contract-migration/config_template/wallet.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[wallet]
|
||||
key_file =
|
||||
passphrase =
|
||||
@@ -14,17 +14,18 @@ RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 2A518C819BE37D2C20
|
||||
RUN mkdir -vp /usr/local/etc/cic
|
||||
|
||||
ENV CONFINI_DIR /usr/local/etc/cic/
|
||||
RUN mkdir -vp $CONFINI_DIR
|
||||
#RUN mkdir -vp $CONFINI_DIR
|
||||
|
||||
ARG cic_config_commit=0abe0867f18077907c7023bf0ef5e466a3984dd8
|
||||
ARG cic_config_url=https://gitlab.com/grassrootseconomics/cic-config.git/
|
||||
RUN echo Install confini schema files && \
|
||||
git clone --depth 1 $cic_config_url cic-config && \
|
||||
cd cic-config && \
|
||||
git fetch --depth 1 origin $cic_config_commit && \
|
||||
git checkout $cic_config_commit && \
|
||||
cp -v *.ini $CONFINI_DIR
|
||||
#ARG cic_config_commit=24287fb253196820f23ff8a7177b122f2cd99a11
|
||||
#ARG cic_config_url=https://gitlab.com/grassrootseconomics/cic-config.git/
|
||||
#RUN echo Install confini schema files && \
|
||||
# git clone --depth 1 $cic_config_url cic-config && \
|
||||
# cd cic-config && \
|
||||
# git fetch --depth 1 origin $cic_config_commit && \
|
||||
# git checkout $cic_config_commit && \
|
||||
# cp -v *.ini $CONFINI_DIR
|
||||
|
||||
COPY config_template/ /usr/local/etc/cic/
|
||||
COPY requirements.txt .
|
||||
|
||||
ARG pip_index_url=https://pypi.org/simple
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
cic_base[full]==0.1.3a4+build.ce68c833
|
||||
sarafu-faucet~=0.0.4a1
|
||||
cic-eth[tools]==0.12.0a2
|
||||
eth-erc20~=0.0.10a3
|
||||
erc20-demurrage-token==0.0.2a3
|
||||
cic-eth[tools]==0.12.2a3
|
||||
eth-erc20>=0.0.11a1,<0.1.0
|
||||
erc20-demurrage-token>=0.0.2a5,<0.1.0
|
||||
eth-address-index>=0.1.3a1,<0.2.0
|
||||
eth-accounts-index>=0.0.13a1,<0.1.0
|
||||
cic-eth-registry>=0.5.7a1,<=0.6.0
|
||||
erc20-faucet>=0.2.3a1,<0.3.0
|
||||
erc20-transfer-authorization>=0.3.3a1,<0.4.0
|
||||
sarafu-faucet>=0.0.4a4,<0.1.0
|
||||
chainlib-eth>=0.0.6a1,<0.1.0
|
||||
|
||||
@@ -148,6 +148,7 @@ else
|
||||
fi
|
||||
|
||||
mkdir -p $CIC_DATA_DIR
|
||||
>&2 echo using data dir $CIC_DATA_DIR for environment variable dump
|
||||
|
||||
# this is consumed in downstream services to set environment variables
|
||||
cat << EOF > $CIC_DATA_DIR/.env
|
||||
@@ -165,4 +166,3 @@ set +e
|
||||
echo -n 2 > $init_level_file
|
||||
|
||||
exec "$@"
|
||||
l:83
|
||||
|
||||
@@ -15,10 +15,6 @@ CIC_DATA_DIR=${CIC_DATA_DIR:-/tmp/cic}
|
||||
ETH_PASSPHRASE=''
|
||||
CIC_DEFAULT_TOKEN_SYMBOL=${CIC_DEFAULT_TOKEN_SYMBOL:-GFT}
|
||||
TOKEN_SYMBOL=$CIC_DEFAULT_TOKEN_SYMBOL
|
||||
if [[ $CIC_DEFAULT_TOKEN_SYMBOL != 'GFT' && $CIC_DEFAULT_TOKEN_SYMBOL != 'SRF' ]]; then
|
||||
>&2 echo CIC_DEFAULT_TOKEN_SYMBOL must be one of [GFT,SRF], but was $CIC_DEFAULT_TOKEN_SYMBOL
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Debug flag
|
||||
DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER=0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C
|
||||
@@ -76,14 +72,16 @@ cic-eth-tag -i $CIC_CHAIN_SPEC ACCOUNT_REGISTRY_WRITER $DEV_ETH_ACCOUNT_ACCOUNT_
|
||||
eth-accounts-index-writer -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -a $DEV_ACCOUNT_INDEX_ADDRESS -ww $debug $DEV_ETH_ACCOUNT_ACCOUNT_REGISTRY_WRITER
|
||||
|
||||
# Transfer gas to custodial gas provider adddress
|
||||
_CONFINI_DIR=$CONFINI_DIR
|
||||
unset CONFINI_DIR
|
||||
>&2 echo gift gas to gas gifter
|
||||
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_GAS_GIFTER $gas_amount
|
||||
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug -a $DEV_ETH_ACCOUNT_GAS_GIFTER $gas_amount
|
||||
|
||||
>&2 echo gift gas to sarafu token owner
|
||||
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_SARAFU_GIFTER $gas_amount
|
||||
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug -a $DEV_ETH_ACCOUNT_SARAFU_GIFTER $gas_amount
|
||||
|
||||
>&2 echo gift gas to account index owner
|
||||
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug $DEV_ETH_ACCOUNT_ACCOUNT_REGISTRY_WRITER $gas_amount
|
||||
>&2 eth-gas --send -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w $debug -a $DEV_ETH_ACCOUNT_ACCOUNT_REGISTRY_WRITER $gas_amount
|
||||
|
||||
|
||||
# Send token to token creator
|
||||
@@ -104,6 +102,7 @@ export DEV_ETH_SARAFU_TOKEN_ADDRESS=$DEV_ETH_RESERVE_ADDRESS
|
||||
|
||||
#echo -n 0 > $init_level_file
|
||||
|
||||
CONFINI_DIR=$_CONFINI_DIR
|
||||
# Remove the SEND (8), QUEUE (16) and INIT (2) locks (or'ed), set by default at migration
|
||||
cic-eth-ctl -i :: unlock INIT
|
||||
cic-eth-ctl -i :: unlock SEND
|
||||
|
||||
@@ -167,7 +167,7 @@ If you have previously run the `cic_ussd` import incompletely, it could be a goo
|
||||
|
||||
Then, in sequence, run in first terminal:
|
||||
|
||||
`python cic_eth/import_balance.py -v -c config -p <eth_provider> -r <cic_registry_address> --token-symbol <token_symbol> -y ../keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c out`
|
||||
`python cic_ussd/import_balance.py -v -c config -p <eth_provider> -r <cic_registry_address> --token-symbol <token_symbol> -y ../contract-migration/keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c out`
|
||||
|
||||
In second terminal:
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import csv
|
||||
import json
|
||||
|
||||
# external imports
|
||||
import eth_abi
|
||||
import confini
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
@@ -29,7 +28,10 @@ from chainlib.eth.gas import OverrideGasOracle
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.error import EthException
|
||||
from chainlib.eth.error import (
|
||||
EthException,
|
||||
RequestMismatchException,
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
|
||||
@@ -37,6 +39,9 @@ from crypto_dev_signer.keystore.dict import DictKeystore
|
||||
from cic_types.models.person import Person
|
||||
from eth_erc20 import ERC20
|
||||
from cic_base.eth.syncer import chain_interface
|
||||
from eth_accounts_index import AccountsIndex
|
||||
from eth_contract_registry import Registry
|
||||
from eth_token_index import TokenUniqueSymbolIndex
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
@@ -131,58 +136,52 @@ class Handler:
|
||||
logg.debug('no payload, skipping {}'.format(tx))
|
||||
return
|
||||
|
||||
if tx.payload[:8] == self.account_index_add_signature:
|
||||
recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:]))
|
||||
#original_address = to_checksum_address(self.addresses[to_checksum_address(recipient)])
|
||||
user_file = 'new/{}/{}/{}.json'.format(
|
||||
recipient[2:4].upper(),
|
||||
recipient[4:6].upper(),
|
||||
recipient[2:].upper(),
|
||||
)
|
||||
filepath = os.path.join(self.user_dir, user_file)
|
||||
o = None
|
||||
try:
|
||||
f = open(filepath, 'r')
|
||||
o = json.load(f)
|
||||
f.close()
|
||||
except FileNotFoundError:
|
||||
logg.error('no import record of address {}'.format(recipient))
|
||||
return
|
||||
u = Person.deserialize(o)
|
||||
original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0]
|
||||
try:
|
||||
balance = self.balances[original_address]
|
||||
except KeyError as e:
|
||||
logg.error('balance get fail orig {} new {}'.format(original_address, recipient))
|
||||
return
|
||||
|
||||
# TODO: store token object in handler ,get decimals from there
|
||||
multiplier = 10**6
|
||||
balance_full = balance * multiplier
|
||||
logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full))
|
||||
|
||||
(tx_hash_hex, o) = self.tx_factory.transfer(self.token_address, signer_address, recipient, balance_full)
|
||||
logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient))
|
||||
r = conn.do(o)
|
||||
|
||||
tx_path = os.path.join(
|
||||
user_dir,
|
||||
'txs',
|
||||
strip_0x(tx_hash_hex),
|
||||
)
|
||||
f = open(tx_path, 'w')
|
||||
f.write(strip_0x(o['params'][0]))
|
||||
recipient = None
|
||||
try:
|
||||
r = AccountsIndex.parse_add_request(tx.payload)
|
||||
except RequestMismatchException:
|
||||
return
|
||||
recipient = r[0]
|
||||
|
||||
user_file = 'new/{}/{}/{}.json'.format(
|
||||
recipient[2:4].upper(),
|
||||
recipient[4:6].upper(),
|
||||
recipient[2:].upper(),
|
||||
)
|
||||
filepath = os.path.join(self.user_dir, user_file)
|
||||
o = None
|
||||
try:
|
||||
f = open(filepath, 'r')
|
||||
o = json.load(f)
|
||||
f.close()
|
||||
# except TypeError as e:
|
||||
# logg.warning('typerror {}'.format(e))
|
||||
# pass
|
||||
# except IndexError as e:
|
||||
# logg.warning('indexerror {}'.format(e))
|
||||
# pass
|
||||
# except EthException as e:
|
||||
# logg.error('send error {}'.format(e).ljust(200))
|
||||
#except KeyError as e:
|
||||
# logg.error('key record not found in imports: {}'.format(e).ljust(200))
|
||||
except FileNotFoundError:
|
||||
logg.error('no import record of address {}'.format(recipient))
|
||||
return
|
||||
u = Person.deserialize(o)
|
||||
original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0]
|
||||
try:
|
||||
balance = self.balances[original_address]
|
||||
except KeyError as e:
|
||||
logg.error('balance get fail orig {} new {}'.format(original_address, recipient))
|
||||
return
|
||||
|
||||
# TODO: store token object in handler ,get decimals from there
|
||||
multiplier = 10**6
|
||||
balance_full = balance * multiplier
|
||||
logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full))
|
||||
|
||||
(tx_hash_hex, o) = self.tx_factory.transfer(self.token_address, signer_address, recipient, balance_full)
|
||||
logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient))
|
||||
r = conn.do(o)
|
||||
|
||||
tx_path = os.path.join(
|
||||
user_dir,
|
||||
'txs',
|
||||
strip_0x(tx_hash_hex),
|
||||
)
|
||||
f = open(tx_path, 'w')
|
||||
f.write(strip_0x(o['params'][0]))
|
||||
f.close()
|
||||
|
||||
|
||||
def progress_callback(block_number, tx_index):
|
||||
@@ -198,49 +197,26 @@ def main():
|
||||
nonce_oracle = RPCNonceOracle(signer_address, conn)
|
||||
|
||||
# Get Token registry address
|
||||
txf = TxFactory(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=None)
|
||||
tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS'))
|
||||
|
||||
registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8]
|
||||
data = add_0x(registry_addressof_method)
|
||||
data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex()
|
||||
txf.set_code(tx, data)
|
||||
|
||||
j = JSONRPCRequest()
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
registry = Registry(chain_spec)
|
||||
o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry')
|
||||
r = conn.do(o)
|
||||
token_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
token_index_address = registry.parse_address_of(r)
|
||||
token_index_address = to_checksum_address(token_index_address)
|
||||
logg.info('found token index address {}'.format(token_index_address))
|
||||
|
||||
|
||||
|
||||
# Get Sarafu token address
|
||||
tx = txf.template(signer_address, token_index_address)
|
||||
data = add_0x(registry_addressof_method)
|
||||
h = hashlib.new('sha256')
|
||||
h.update(token_symbol.encode('utf-8'))
|
||||
z = h.digest()
|
||||
data += eth_abi.encode_single('bytes32', z).hex()
|
||||
txf.set_code(tx, data)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
token_index = TokenUniqueSymbolIndex(chain_spec)
|
||||
o = token_index.address_of(token_index_address, token_symbol)
|
||||
r = conn.do(o)
|
||||
token_address = token_index.parse_address_of(r)
|
||||
try:
|
||||
sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
token_address = to_checksum_address(token_address)
|
||||
except ValueError as e:
|
||||
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
|
||||
sys.exit(1)
|
||||
|
||||
if sarafu_token_address == ZERO_ADDRESS:
|
||||
raise KeyError('token address for symbol {} is zero'.format(token_symbol))
|
||||
|
||||
logg.info('found token address {}'.format(sarafu_token_address))
|
||||
logg.info('found token address {}'.format(token_address))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
syncer_backend = MemBackend(chain_str, 0)
|
||||
|
||||
@@ -248,22 +224,6 @@ def main():
|
||||
o = block_latest()
|
||||
r = conn.do(o)
|
||||
block_offset = int(strip_0x(r), 16) + 1
|
||||
#
|
||||
# addresses = {}
|
||||
# f = open('{}/addresses.csv'.format(user_dir, 'r'))
|
||||
# while True:
|
||||
# l = f.readline()
|
||||
# if l == None:
|
||||
# break
|
||||
# r = l.split(',')
|
||||
# try:
|
||||
# k = r[0]
|
||||
# v = r[1].rstrip()
|
||||
# addresses[k] = v
|
||||
# sys.stdout.write('loading address mapping {} -> {}'.format(k, v).ljust(200) + "\r")
|
||||
# except IndexError as e:
|
||||
# break
|
||||
# f.close()
|
||||
|
||||
# TODO get decimals from token
|
||||
balances = {}
|
||||
|
||||
@@ -11,7 +11,6 @@ const config = new crdt.Config('./config');
|
||||
config.process();
|
||||
console.log(config);
|
||||
|
||||
|
||||
function sendit(uid, envelope) {
|
||||
const d = envelope.toJSON();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ default_config_dir = '/usr/local/etc/cic'
|
||||
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument('-c', type=str, default=default_config_dir, help='config file')
|
||||
arg_parser.add_argument('-q', type=str, default='cic-eth', help='Task queue')
|
||||
arg_parser.add_argument('-q', type=str, default='cic-import-ussd', help='Task queue')
|
||||
arg_parser.add_argument('-v', action='store_true', help='Be verbose')
|
||||
arg_parser.add_argument('-vv', action='store_true', help='Be more verbose')
|
||||
arg_parser.add_argument('user_dir', type=str, help='path to users export dir tree')
|
||||
|
||||
@@ -206,7 +206,7 @@ def gen():
|
||||
# fake.local_latitude()
|
||||
p.location['latitude'] = (random.random() * 180) - 90
|
||||
# fake.local_latitude()
|
||||
p.location['longitude'] = (random.random() * 360) - 179
|
||||
p.location['longitude'] = (random.random() * 360) - 180
|
||||
|
||||
return (old_blockchain_checksum_address, phone, p)
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import csv
|
||||
import json
|
||||
|
||||
# external imports
|
||||
import eth_abi
|
||||
import confini
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
@@ -29,13 +28,20 @@ from chainlib.eth.gas import OverrideGasOracle
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.tx import TxFactory
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.eth.error import EthException
|
||||
from chainlib.eth.error import (
|
||||
EthException,
|
||||
RequestMismatchException,
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
|
||||
from crypto_dev_signer.keystore.dict import DictKeystore
|
||||
from cic_types.models.person import Person
|
||||
from eth_erc20 import ERC20
|
||||
from cic_base.eth.syncer import chain_interface
|
||||
from eth_accounts_index import AccountsIndex
|
||||
from eth_contract_registry import Registry
|
||||
from eth_token_index import TokenUniqueSymbolIndex
|
||||
from erc20_faucet import Faucet
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
@@ -50,7 +56,7 @@ argparser.add_argument('-c', type=str, default=config_dir, help='config root to
|
||||
argparser.add_argument('--old-chain-spec', type=str, dest='old_chain_spec', default='evm:oldchain:1', help='chain spec')
|
||||
argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spec')
|
||||
argparser.add_argument('-r', '--registry-address', type=str, dest='r', help='CIC Registry address')
|
||||
argparser.add_argument('--token-symbol', default='SRF', type=str, dest='token_symbol', help='Token symbol to use for trnsactions')
|
||||
argparser.add_argument('--token-symbol', default='GFT', type=str, dest='token_symbol', help='Token symbol to use for trnsactions')
|
||||
argparser.add_argument('--head', action='store_true', help='start at current block height (overrides --offset)')
|
||||
argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration')
|
||||
argparser.add_argument('-q', type=str, default='cic-eth', help='celery queue to submit transaction tasks to')
|
||||
@@ -112,12 +118,16 @@ class Handler:
|
||||
|
||||
account_index_add_signature = keccak256_string_to_hex('add(address)')[:8]
|
||||
|
||||
def __init__(self, conn, chain_spec, user_dir, balances, token_address, signer, gas_oracle, nonce_oracle):
|
||||
def __init__(self, conn, chain_spec, user_dir, balances, token_address, faucet_address, signer_address, signer, gas_oracle, nonce_oracle):
|
||||
self.token_address = token_address
|
||||
self.faucet_address = faucet_address
|
||||
self.user_dir = user_dir
|
||||
self.balances = balances
|
||||
self.chain_spec = chain_spec
|
||||
self.tx_factory = ERC20(chain_spec, signer, gas_oracle, nonce_oracle)
|
||||
self.nonce_oracle = nonce_oracle
|
||||
self.gas_oracle = gas_oracle
|
||||
self.signer_address = signer_address
|
||||
self.signer = signer
|
||||
|
||||
|
||||
def name(self):
|
||||
@@ -129,58 +139,59 @@ class Handler:
|
||||
logg.debug('no payload, skipping {}'.format(tx))
|
||||
return
|
||||
|
||||
if tx.payload[:8] == self.account_index_add_signature:
|
||||
recipient = eth_abi.decode_single('address', bytes.fromhex(tx.payload[-64:]))
|
||||
#original_address = to_checksum_address(self.addresses[to_checksum_address(recipient)])
|
||||
user_file = 'new/{}/{}/{}.json'.format(
|
||||
recipient[2:4].upper(),
|
||||
recipient[4:6].upper(),
|
||||
recipient[2:].upper(),
|
||||
)
|
||||
filepath = os.path.join(self.user_dir, user_file)
|
||||
o = None
|
||||
try:
|
||||
f = open(filepath, 'r')
|
||||
o = json.load(f)
|
||||
f.close()
|
||||
except FileNotFoundError:
|
||||
logg.error('no import record of address {}'.format(recipient))
|
||||
return
|
||||
u = Person.deserialize(o)
|
||||
original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0]
|
||||
try:
|
||||
balance = self.balances[original_address]
|
||||
except KeyError as e:
|
||||
logg.error('balance get fail orig {} new {}'.format(original_address, recipient))
|
||||
return
|
||||
|
||||
# TODO: store token object in handler ,get decimals from there
|
||||
multiplier = 10**6
|
||||
balance_full = balance * multiplier
|
||||
logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full))
|
||||
|
||||
(tx_hash_hex, o) = self.tx_factory.transfer(self.token_address, signer_address, recipient, balance_full)
|
||||
logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient))
|
||||
r = conn.do(o)
|
||||
|
||||
tx_path = os.path.join(
|
||||
user_dir,
|
||||
'txs',
|
||||
strip_0x(tx_hash_hex),
|
||||
)
|
||||
f = open(tx_path, 'w')
|
||||
f.write(strip_0x(o['params'][0]))
|
||||
recipient = None
|
||||
try:
|
||||
r = AccountsIndex.parse_add_request(tx.payload)
|
||||
except RequestMismatchException:
|
||||
return
|
||||
recipient = r[0]
|
||||
|
||||
user_file = 'new/{}/{}/{}.json'.format(
|
||||
recipient[2:4].upper(),
|
||||
recipient[4:6].upper(),
|
||||
recipient[2:].upper(),
|
||||
)
|
||||
filepath = os.path.join(self.user_dir, user_file)
|
||||
o = None
|
||||
try:
|
||||
f = open(filepath, 'r')
|
||||
o = json.load(f)
|
||||
f.close()
|
||||
# except TypeError as e:
|
||||
# logg.warning('typerror {}'.format(e))
|
||||
# pass
|
||||
# except IndexError as e:
|
||||
# logg.warning('indexerror {}'.format(e))
|
||||
# pass
|
||||
# except EthException as e:
|
||||
# logg.error('send error {}'.format(e).ljust(200))
|
||||
#except KeyError as e:
|
||||
# logg.error('key record not found in imports: {}'.format(e).ljust(200))
|
||||
except FileNotFoundError:
|
||||
logg.error('no import record of address {}'.format(recipient))
|
||||
return
|
||||
u = Person.deserialize(o)
|
||||
original_address = u.identities[old_chain_spec.engine()]['{}:{}'.format(old_chain_spec.common_name(), old_chain_spec.network_id())][0]
|
||||
try:
|
||||
balance = self.balances[original_address]
|
||||
except KeyError as e:
|
||||
logg.error('balance get fail orig {} new {}'.format(original_address, recipient))
|
||||
return
|
||||
|
||||
# TODO: store token object in handler ,get decimals from there
|
||||
erc20 = ERC20(self.chain_spec, signer=self.signer, gas_oracle=self.gas_oracle, nonce_oracle=self.nonce_oracle)
|
||||
o = erc20.decimals(self.token_address)
|
||||
r = conn.do(o)
|
||||
decimals = erc20.parse_decimals(r)
|
||||
multiplier = 10 ** decimals
|
||||
balance_full = balance * multiplier
|
||||
logg.info('registered {} originally {} ({}) tx hash {} balance {}'.format(recipient, original_address, u, tx.hash, balance_full))
|
||||
(tx_hash_hex, o) = erc20.transfer(self.token_address, self.signer_address, recipient, balance_full)
|
||||
logg.info('submitting erc20 transfer tx {} for recipient {}'.format(tx_hash_hex, recipient))
|
||||
r = conn.do(o)
|
||||
|
||||
tx_path = os.path.join(
|
||||
user_dir,
|
||||
'txs',
|
||||
strip_0x(tx_hash_hex),
|
||||
)
|
||||
f = open(tx_path, 'w')
|
||||
f.write(strip_0x(o['params'][0]))
|
||||
f.close()
|
||||
|
||||
faucet = Faucet(self.chain_spec, signer=self.signer, gas_oracle=self.gas_oracle, nonce_oracle=self.nonce_oracle)
|
||||
(tx_hash, o) = faucet.give_to(self.faucet_address, self.signer_address, recipient)
|
||||
r = conn.do(o)
|
||||
|
||||
|
||||
def progress_callback(block_number, tx_index):
|
||||
@@ -196,45 +207,31 @@ def main():
|
||||
nonce_oracle = RPCNonceOracle(signer_address, conn)
|
||||
|
||||
# Get Token registry address
|
||||
txf = TxFactory(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=None)
|
||||
tx = txf.template(signer_address, config.get('CIC_REGISTRY_ADDRESS'))
|
||||
|
||||
registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8]
|
||||
data = add_0x(registry_addressof_method)
|
||||
data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex()
|
||||
txf.set_code(tx, data)
|
||||
|
||||
j = JSONRPCRequest()
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
registry = Registry(chain_spec)
|
||||
o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry')
|
||||
r = conn.do(o)
|
||||
token_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
token_index_address = registry.parse_address_of(r)
|
||||
token_index_address = to_checksum_address(token_index_address)
|
||||
logg.info('found token index address {}'.format(token_index_address))
|
||||
|
||||
|
||||
# Get Faucet address
|
||||
o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'Faucet')
|
||||
r = conn.do(o)
|
||||
faucet_address = registry.parse_address_of(r)
|
||||
faucet_address = to_checksum_address(faucet_address)
|
||||
logg.info('found faucet {}'.format(faucet_address))
|
||||
|
||||
# Get Sarafu token address
|
||||
tx = txf.template(signer_address, token_index_address)
|
||||
data = add_0x(registry_addressof_method)
|
||||
h = hashlib.new('sha256')
|
||||
h.update(token_symbol.encode('utf-8'))
|
||||
z = h.digest()
|
||||
data += eth_abi.encode_single('bytes32', z).hex()
|
||||
txf.set_code(tx, data)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
token_index = TokenUniqueSymbolIndex(chain_spec)
|
||||
o = token_index.address_of(token_index_address, token_symbol)
|
||||
r = conn.do(o)
|
||||
token_address = token_index.parse_address_of(r)
|
||||
try:
|
||||
sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
token_address = to_checksum_address(token_address)
|
||||
except ValueError as e:
|
||||
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
|
||||
sys.exit(1)
|
||||
logg.info('found token address {}'.format(sarafu_token_address))
|
||||
logg.info('found token address {}'.format(token_address))
|
||||
|
||||
syncer_backend = MemBackend(chain_str, 0)
|
||||
|
||||
@@ -242,22 +239,6 @@ def main():
|
||||
o = block_latest()
|
||||
r = conn.do(o)
|
||||
block_offset = int(strip_0x(r), 16) + 1
|
||||
#
|
||||
# addresses = {}
|
||||
# f = open('{}/addresses.csv'.format(user_dir, 'r'))
|
||||
# while True:
|
||||
# l = f.readline()
|
||||
# if l == None:
|
||||
# break
|
||||
# r = l.split(',')
|
||||
# try:
|
||||
# k = r[0]
|
||||
# v = r[1].rstrip()
|
||||
# addresses[k] = v
|
||||
# sys.stdout.write('loading address mapping {} -> {}'.format(k, v).ljust(200) + "\r")
|
||||
# except IndexError as e:
|
||||
# break
|
||||
# f.close()
|
||||
|
||||
# TODO get decimals from token
|
||||
balances = {}
|
||||
@@ -282,7 +263,7 @@ def main():
|
||||
|
||||
syncer_backend.set(block_offset, 0)
|
||||
syncer = HeadSyncer(syncer_backend, chain_interface, block_callback=progress_callback)
|
||||
handler = Handler(conn, chain_spec, user_dir, balances, sarafu_token_address, signer, gas_oracle, nonce_oracle)
|
||||
handler = Handler(conn, chain_spec, user_dir, balances, token_address, faucet_address, signer_address, signer, gas_oracle, nonce_oracle)
|
||||
syncer.add_filter(handler)
|
||||
syncer.loop(1, conn)
|
||||
|
||||
|
||||
145
apps/data-seeding/package-lock.json
generated
145
apps/data-seeding/package-lock.json
generated
@@ -6,7 +6,7 @@
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@cicnet/cic-client-meta": "^0.0.11",
|
||||
"@cicnet/crdt-meta": "^0.0.10",
|
||||
"@cicnet/crdt-meta": "^0.0.12",
|
||||
"vcard-parser": "^1.0.0"
|
||||
}
|
||||
},
|
||||
@@ -34,7 +34,7 @@
|
||||
"node": ">=14.16.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@cicnet/crdt-meta": {
|
||||
"node_modules/@cicnet/cic-client-meta/node_modules/@cicnet/crdt-meta": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz",
|
||||
"integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==",
|
||||
@@ -48,22 +48,36 @@
|
||||
"node": ">=14.16.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@cicnet/crdt-meta": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.12.tgz",
|
||||
"integrity": "sha512-wPX86P1Lsq4RxkVUlhlouhLkMOtkqzHgpNuXicHvWuhH3ks2Nsg7yqvTw9yt+kqj+N8a5pPMrNhKvUEFW8rJjA==",
|
||||
"dependencies": {
|
||||
"automerge": "^0.14.2",
|
||||
"ini": "^1.3.8",
|
||||
"openpgp": "^4.10.8",
|
||||
"readline-sync": "^1.4.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@ethereumjs/common": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.3.0.tgz",
|
||||
"integrity": "sha512-Fmi15MdVptsC85n6NcUXIFiiXCXWEfZNgPWP+OGAQOC6ZtdzoNawtxH/cYpIgEgSuIzfOeX3VKQP/qVI1wISHg==",
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.4.0.tgz",
|
||||
"integrity": "sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==",
|
||||
"dependencies": {
|
||||
"crc-32": "^1.2.0",
|
||||
"ethereumjs-util": "^7.0.10"
|
||||
"ethereumjs-util": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ethereumjs/tx": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.2.0.tgz",
|
||||
"integrity": "sha512-D3X/XtZ3ldUg34hr99Jvj7NxW3NxVKdUKrwQnEWlAp4CmCQpvYoyn7NF4lk34rHEt7ScS+Agu01pcDHoOcd19A==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.0.tgz",
|
||||
"integrity": "sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==",
|
||||
"dependencies": {
|
||||
"@ethereumjs/common": "^2.3.0",
|
||||
"ethereumjs-util": "^7.0.10"
|
||||
"@ethereumjs/common": "^2.4.0",
|
||||
"ethereumjs-util": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/bn.js": {
|
||||
@@ -75,9 +89,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "15.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz",
|
||||
"integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw=="
|
||||
"version": "16.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz",
|
||||
"integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw=="
|
||||
},
|
||||
"node_modules/@types/pbkdf2": {
|
||||
"version": "3.1.0",
|
||||
@@ -88,9 +102,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/secp256k1": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz",
|
||||
"integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz",
|
||||
"integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@@ -273,9 +287,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/blakejs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
|
||||
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz",
|
||||
"integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg=="
|
||||
},
|
||||
"node_modules/block-stream": {
|
||||
"version": "0.0.9",
|
||||
@@ -639,9 +653,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ethereumjs-util": {
|
||||
"version": "7.0.10",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
|
||||
"integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz",
|
||||
"integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==",
|
||||
"dependencies": {
|
||||
"@types/bn.js": "^5.1.0",
|
||||
"bn.js": "^5.1.2",
|
||||
@@ -1148,9 +1162,9 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/needle": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz",
|
||||
"integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==",
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz",
|
||||
"integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==",
|
||||
"dependencies": {
|
||||
"debug": "^3.2.6",
|
||||
"iconv-lite": "^0.4.4",
|
||||
@@ -2125,9 +2139,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "20.2.7",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz",
|
||||
"integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==",
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -2189,12 +2203,25 @@
|
||||
"pg": "^8.4.2",
|
||||
"sqlite3": "^5.0.0",
|
||||
"yargs": "^16.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cicnet/crdt-meta": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz",
|
||||
"integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==",
|
||||
"requires": {
|
||||
"automerge": "^0.14.2",
|
||||
"ini": "^1.3.8",
|
||||
"openpgp": "^4.10.8",
|
||||
"readline-sync": "^1.4.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@cicnet/crdt-meta": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.10.tgz",
|
||||
"integrity": "sha512-f+H6BQA2tE718KuNYiNzrDJN4wY00zeuhXM6aPKJUX6nryzX9g2r0yf8iDhkz+Fts1R6M7Riz73MfFEa8fgvsw==",
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@cicnet/crdt-meta/-/crdt-meta-0.0.12.tgz",
|
||||
"integrity": "sha512-wPX86P1Lsq4RxkVUlhlouhLkMOtkqzHgpNuXicHvWuhH3ks2Nsg7yqvTw9yt+kqj+N8a5pPMrNhKvUEFW8rJjA==",
|
||||
"requires": {
|
||||
"automerge": "^0.14.2",
|
||||
"ini": "^1.3.8",
|
||||
@@ -2203,21 +2230,21 @@
|
||||
}
|
||||
},
|
||||
"@ethereumjs/common": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.3.0.tgz",
|
||||
"integrity": "sha512-Fmi15MdVptsC85n6NcUXIFiiXCXWEfZNgPWP+OGAQOC6ZtdzoNawtxH/cYpIgEgSuIzfOeX3VKQP/qVI1wISHg==",
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.4.0.tgz",
|
||||
"integrity": "sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==",
|
||||
"requires": {
|
||||
"crc-32": "^1.2.0",
|
||||
"ethereumjs-util": "^7.0.10"
|
||||
"ethereumjs-util": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"@ethereumjs/tx": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.2.0.tgz",
|
||||
"integrity": "sha512-D3X/XtZ3ldUg34hr99Jvj7NxW3NxVKdUKrwQnEWlAp4CmCQpvYoyn7NF4lk34rHEt7ScS+Agu01pcDHoOcd19A==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.0.tgz",
|
||||
"integrity": "sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==",
|
||||
"requires": {
|
||||
"@ethereumjs/common": "^2.3.0",
|
||||
"ethereumjs-util": "^7.0.10"
|
||||
"@ethereumjs/common": "^2.4.0",
|
||||
"ethereumjs-util": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"@types/bn.js": {
|
||||
@@ -2229,9 +2256,9 @@
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "15.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz",
|
||||
"integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw=="
|
||||
"version": "16.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz",
|
||||
"integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw=="
|
||||
},
|
||||
"@types/pbkdf2": {
|
||||
"version": "3.1.0",
|
||||
@@ -2242,9 +2269,9 @@
|
||||
}
|
||||
},
|
||||
"@types/secp256k1": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz",
|
||||
"integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz",
|
||||
"integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@@ -2412,9 +2439,9 @@
|
||||
}
|
||||
},
|
||||
"blakejs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
|
||||
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz",
|
||||
"integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg=="
|
||||
},
|
||||
"block-stream": {
|
||||
"version": "0.0.9",
|
||||
@@ -2728,9 +2755,9 @@
|
||||
}
|
||||
},
|
||||
"ethereumjs-util": {
|
||||
"version": "7.0.10",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
|
||||
"integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz",
|
||||
"integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==",
|
||||
"requires": {
|
||||
"@types/bn.js": "^5.1.0",
|
||||
"bn.js": "^5.1.2",
|
||||
@@ -3157,9 +3184,9 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"needle": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz",
|
||||
"integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==",
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz",
|
||||
"integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==",
|
||||
"requires": {
|
||||
"debug": "^3.2.6",
|
||||
"iconv-lite": "^0.4.4",
|
||||
@@ -3944,9 +3971,9 @@
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "20.2.7",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz",
|
||||
"integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw=="
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@cicnet/cic-client-meta": "^0.0.11",
|
||||
"@cicnet/crdt-meta": "^0.0.10",
|
||||
"@cicnet/crdt-meta": "^0.0.12",
|
||||
"vcard-parser": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
sarafu-faucet==0.0.4a1
|
||||
cic-eth[tools]==0.12.0a1
|
||||
sarafu-faucet==0.0.4a3
|
||||
cic-eth[tools]==0.12.1a1
|
||||
cic-types==0.1.0a13
|
||||
crypto-dev-signer==0.4.14b6
|
||||
crypto-dev-signer==0.4.14b7
|
||||
faker==4.17.1
|
||||
chainsyncer~=0.0.3a3
|
||||
chainlib-eth~=0.0.5a1
|
||||
eth-address-index~=0.1.2a1
|
||||
eth-contract-registry~=0.5.6a1
|
||||
eth-accounts-index~=0.0.12a1
|
||||
eth-erc20~=0.0.10a3
|
||||
erc20-faucet~=0.2.2a1
|
||||
psycopg2==2.8.6
|
||||
|
||||
@@ -14,7 +14,6 @@ import urllib.parse
|
||||
# external imports
|
||||
import celery
|
||||
import confini
|
||||
import eth_abi
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.address import to_checksum_address
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
@@ -33,6 +32,9 @@ from cic_types.models.person import (
|
||||
from erc20_faucet import Faucet
|
||||
from eth_erc20 import ERC20
|
||||
from hexathon.parse import strip_0x, add_0x
|
||||
from eth_contract_registry import Registry
|
||||
from eth_accounts_index import AccountsIndex
|
||||
from eth_token_index import TokenUniqueSymbolIndex
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
@@ -43,7 +45,8 @@ custodial_tests = [
|
||||
'local_key',
|
||||
'gas',
|
||||
'faucet',
|
||||
'ussd'
|
||||
'ussd',
|
||||
'ussd_pins',
|
||||
]
|
||||
|
||||
metadata_tests = [
|
||||
@@ -71,6 +74,7 @@ argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spe
|
||||
argparser.add_argument('--meta-provider', type=str, dest='meta_provider', default='http://localhost:63380', help='cic-meta url')
|
||||
argparser.add_argument('--ussd-provider', type=str, dest='ussd_provider', default='http://localhost:63315', help='cic-ussd url')
|
||||
argparser.add_argument('--skip-custodial', dest='skip_custodial', action='store_true', help='skip all custodial verifications')
|
||||
argparser.add_argument('--skip-metadata', dest='skip_metadata', action='store_true', help='skip all metadata verifications')
|
||||
argparser.add_argument('--exclude', action='append', type=str, default=[], help='skip specified verification')
|
||||
argparser.add_argument('--include', action='append', type=str, help='include specified verification')
|
||||
argparser.add_argument('--token-symbol', default='GFT', type=str, dest='token_symbol', help='Token symbol to use for trnsactions')
|
||||
@@ -130,6 +134,11 @@ if args.skip_custodial:
|
||||
for t in custodial_tests:
|
||||
if t not in exclude:
|
||||
exclude.append(t)
|
||||
if args.skip_metadata:
|
||||
logg.info('will skip all metadata verifications ({})'.format(','.join(metadata_tests)))
|
||||
for t in metadata_tests:
|
||||
if t not in exclude:
|
||||
exclude.append(t)
|
||||
for t in include:
|
||||
if t not in all_tests:
|
||||
raise ValueError('Cannot include unknown verification "{}"'.format(t))
|
||||
@@ -140,7 +149,7 @@ for t in include:
|
||||
api = None
|
||||
for t in custodial_tests:
|
||||
if t in active_tests:
|
||||
from cic_eth.api.api_admin import AdminApi
|
||||
from cic_eth.api.admin import AdminApi
|
||||
api = AdminApi(None)
|
||||
logg.info('activating custodial module'.format(t))
|
||||
break
|
||||
@@ -263,19 +272,11 @@ class Verifier:
|
||||
|
||||
|
||||
def verify_accounts_index(self, address, balance=None):
|
||||
tx = self.tx_factory.template(ZERO_ADDRESS, self.index_address)
|
||||
data = keccak256_string_to_hex('have(address)')[:8]
|
||||
data += eth_abi.encode_single('address', address).hex()
|
||||
tx = self.tx_factory.set_code(tx, data)
|
||||
tx = self.tx_factory.normalize(tx)
|
||||
j = JSONRPCRequest()
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(tx)
|
||||
o = j.finalize(o)
|
||||
accounts_index = AccountsIndex(self.chain_spec)
|
||||
o = accounts_index.have(self.index_address, address)
|
||||
r = self.conn.do(o)
|
||||
logg.debug('index check for {}: {}'.format(address, r))
|
||||
n = eth_abi.decode_single('uint256', bytes.fromhex(strip_0x(r)))
|
||||
n = accounts_index.parse_have(r)
|
||||
logg.debug('index check for {}: {}'.format(address, n))
|
||||
if n != 1:
|
||||
raise VerifierError(n, 'accounts index')
|
||||
|
||||
@@ -289,7 +290,7 @@ class Verifier:
|
||||
actual_balance = int(r)
|
||||
balance = int(balance / 1000000) * 1000000
|
||||
balance += self.faucet_amount
|
||||
logg.debug('balance for {}: {}'.format(address, balance))
|
||||
logg.info('balance for {}: {}'.format(address, balance))
|
||||
if balance != actual_balance:
|
||||
raise VerifierError((actual_balance, balance), 'balance')
|
||||
|
||||
@@ -427,70 +428,39 @@ def main():
|
||||
gas_oracle = OverrideGasOracle(conn=conn, limit=8000000)
|
||||
|
||||
# Get Token registry address
|
||||
txf = TxFactory(chain_spec, signer=None, gas_oracle=gas_oracle, nonce_oracle=None)
|
||||
tx = txf.template(ZERO_ADDRESS, config.get('CIC_REGISTRY_ADDRESS'))
|
||||
|
||||
# TODO: replace with cic-eth-registry
|
||||
registry_addressof_method = keccak256_string_to_hex('addressOf(bytes32)')[:8]
|
||||
data = add_0x(registry_addressof_method)
|
||||
data += eth_abi.encode_single('bytes32', b'TokenRegistry').hex()
|
||||
txf.set_code(tx, data)
|
||||
|
||||
j = JSONRPCRequest()
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
registry = Registry(chain_spec)
|
||||
o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'TokenRegistry')
|
||||
r = conn.do(o)
|
||||
token_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
token_index_address = registry.parse_address_of(r)
|
||||
token_index_address = to_checksum_address(token_index_address)
|
||||
logg.info('found token index address {}'.format(token_index_address))
|
||||
|
||||
data = add_0x(registry_addressof_method)
|
||||
data += eth_abi.encode_single('bytes32', b'AccountRegistry').hex()
|
||||
txf.set_code(tx, data)
|
||||
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
# Get Account registry address
|
||||
o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'AccountRegistry')
|
||||
r = conn.do(o)
|
||||
account_index_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
account_index_address = registry.parse_address_of(r)
|
||||
account_index_address = to_checksum_address(account_index_address)
|
||||
logg.info('found account index address {}'.format(account_index_address))
|
||||
|
||||
data = add_0x(registry_addressof_method)
|
||||
data += eth_abi.encode_single('bytes32', b'Faucet').hex()
|
||||
txf.set_code(tx, data)
|
||||
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
# Get Faucet address
|
||||
o = registry.address_of(config.get('CIC_REGISTRY_ADDRESS'), 'Faucet')
|
||||
r = conn.do(o)
|
||||
faucet_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
faucet_address = registry.parse_address_of(r)
|
||||
faucet_index_address = to_checksum_address(token_index_address)
|
||||
logg.info('found faucet {}'.format(faucet_address))
|
||||
|
||||
|
||||
|
||||
# Get Sarafu token address
|
||||
tx = txf.template(ZERO_ADDRESS, token_index_address)
|
||||
data = add_0x(registry_addressof_method)
|
||||
h = hashlib.new('sha256')
|
||||
h.update(token_symbol.encode('utf-8'))
|
||||
z = h.digest()
|
||||
data += eth_abi.encode_single('bytes32', z).hex()
|
||||
txf.set_code(tx, data)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_call'
|
||||
o['params'].append(txf.normalize(tx))
|
||||
o['params'].append('latest')
|
||||
o = j.finalize(o)
|
||||
# Get Sarafu token address
|
||||
token_index = TokenUniqueSymbolIndex(chain_spec)
|
||||
o = token_index.address_of(token_index_address, token_symbol)
|
||||
r = conn.do(o)
|
||||
sarafu_token_address = to_checksum_address(eth_abi.decode_single('address', bytes.fromhex(strip_0x(r))))
|
||||
logg.info('found token address {}'.format(sarafu_token_address))
|
||||
|
||||
token_address = token_index.parse_address_of(r)
|
||||
try:
|
||||
token_address = to_checksum_address(token_address)
|
||||
except ValueError as e:
|
||||
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
|
||||
sys.exit(1)
|
||||
logg.info('found token address {}'.format(token_address))
|
||||
|
||||
balances = {}
|
||||
f = open('{}/balances.csv'.format(user_dir, 'r'))
|
||||
i = 0
|
||||
@@ -511,7 +481,7 @@ def main():
|
||||
|
||||
f.close()
|
||||
|
||||
verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, sarafu_token_address, faucet_address, user_dir, exit_on_error)
|
||||
verifier = Verifier(conn, api, gas_oracle, chain_spec, account_index_address, token_address, faucet_address, user_dir, exit_on_error)
|
||||
|
||||
user_new_dir = os.path.join(user_dir, 'new')
|
||||
i = 0
|
||||
|
||||
Reference in New Issue
Block a user