Compare commits
32 Commits
tmp
...
philip/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0490d41aa5 | ||
|
|
22ec8e2e0e
|
||
|
|
a8529ae2ef | ||
|
|
98ddf56a1d | ||
|
|
e2eca335f1
|
||
|
|
be32fc75fc
|
||
|
|
bb930ce148
|
||
|
|
5f99048154
|
||
|
|
2df8e8f299
|
||
|
|
c0a8be637f
|
||
|
|
ddf3ba0d22
|
||
|
|
60033e9f9e
|
||
|
|
30b47f05ef | ||
|
|
7a958c6f89
|
||
|
|
be65da9924
|
||
|
|
fe4bef5290
|
||
|
|
5345803dc7
|
||
|
|
bf8ddd0a5c
|
||
|
|
537ea782c7
|
||
|
|
0c7b78fdf2
|
||
| bee602b16a | |||
| c67274846f | |||
|
|
bb556b5c45 | ||
|
|
25847de75e
|
||
|
|
48570b2338 | ||
|
|
c80b8771b9 | ||
|
|
6535760abb
|
||
|
689f04c1be
|
|||
|
f03d3c4390
|
|||
|
32ce66ce43
|
|||
|
b8fbf512fb
|
|||
|
3aaa42a1a7
|
@@ -26,7 +26,7 @@ from chainlib.eth.block import (
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
)
|
||||
from chainsyncer.backend import SyncerBackend
|
||||
from chainsyncer.backend.sql import SQLBackend
|
||||
from chainsyncer.driver import (
|
||||
HeadSyncer,
|
||||
HistorySyncer,
|
||||
@@ -71,13 +71,13 @@ def main():
|
||||
|
||||
syncers = []
|
||||
|
||||
#if SyncerBackend.first(chain_spec):
|
||||
# backend = SyncerBackend.initial(chain_spec, block_offset)
|
||||
syncer_backends = SyncerBackend.resume(chain_spec, block_offset)
|
||||
#if SQLBackend.first(chain_spec):
|
||||
# backend = SQLBackend.initial(chain_spec, block_offset)
|
||||
syncer_backends = SQLBackend.resume(chain_spec, block_offset)
|
||||
|
||||
if len(syncer_backends) == 0:
|
||||
logg.info('found no backends to resume')
|
||||
syncers.append(SyncerBackend.initial(chain_spec, block_offset))
|
||||
syncers.append(SQLBackend.initial(chain_spec, block_offset))
|
||||
else:
|
||||
for syncer_backend in syncer_backends:
|
||||
logg.info('resuming sync session {}'.format(syncer_backend))
|
||||
@@ -85,7 +85,7 @@ def main():
|
||||
for syncer_backend in syncer_backends:
|
||||
syncers.append(HistorySyncer(syncer_backend))
|
||||
|
||||
syncer_backend = SyncerBackend.live(chain_spec, block_offset+1)
|
||||
syncer_backend = SQLBackend.live(chain_spec, block_offset+1)
|
||||
syncers.append(HeadSyncer(syncer_backend))
|
||||
|
||||
trusted_addresses_src = config.get('CIC_TRUST_ADDRESS')
|
||||
|
||||
@@ -17,7 +17,7 @@ RUN apt-get update && \
|
||||
|
||||
# Copy shared requirements from top of mono-repo
|
||||
RUN echo "copying root req file ${root_requirement_file}"
|
||||
RUN pip install $pip_extra_index_url_flag cic-base[full_graph]==0.1.2a58
|
||||
RUN pip install $pip_extra_index_url_flag cic-base[full_graph]==0.1.2a76
|
||||
|
||||
COPY cic-cache/requirements.txt ./
|
||||
COPY cic-cache/setup.cfg \
|
||||
@@ -47,6 +47,9 @@ RUN git clone https://gitlab.com/grassrootseconomics/cic-contracts.git && \
|
||||
mkdir -p /usr/local/share/cic/solidity && \
|
||||
cp -R cic-contracts/abis /usr/local/share/cic/solidity/abi
|
||||
|
||||
COPY cic-cache/docker/start_tracker.sh ./start_tracker.sh
|
||||
COPY cic-cache/docker/db.sh ./db.sh
|
||||
RUN chmod 755 ./*.sh
|
||||
# Tracker
|
||||
# ENTRYPOINT ["/usr/local/bin/cic-cache-tracker", "-vv"]
|
||||
# Server
|
||||
|
||||
6
apps/cic-cache/docker/db.sh
Normal file
6
apps/cic-cache/docker/db.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
>&2 echo executing database migration
|
||||
python scripts/migrate.py -c /usr/local/etc/cic-cache --migrations-dir /usr/local/share/cic-cache/alembic -vv
|
||||
set +e
|
||||
5
apps/cic-cache/docker/start_tracker.sh
Normal file
5
apps/cic-cache/docker/start_tracker.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ./db.sh
|
||||
|
||||
/usr/local/bin/cic-cache-trackerd $@
|
||||
@@ -1,13 +1,12 @@
|
||||
cic-base~=0.1.2a66
|
||||
cic-base~=0.1.2a77
|
||||
alembic==1.4.2
|
||||
confini~=0.3.6rc3
|
||||
uwsgi==2.0.19.1
|
||||
moolb~=0.1.0
|
||||
cic-eth-registry~=0.5.4a13
|
||||
cic-eth-registry~=0.5.4a16
|
||||
SQLAlchemy==1.3.20
|
||||
semver==2.13.0
|
||||
psycopg2==2.8.6
|
||||
celery==4.4.7
|
||||
redis==3.5.3
|
||||
chainlib~=0.0.2a10
|
||||
chainsyncer[sql]~=0.0.2a1
|
||||
chainsyncer[sql]~=0.0.2a2
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# extended imports
|
||||
# external imports
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.status import Status as TxStatus
|
||||
from cic_eth_registry.erc20 import ERC20Token
|
||||
|
||||
# local imports
|
||||
from cic_eth.ext.address import translate_address
|
||||
|
||||
|
||||
class ExtendedTx:
|
||||
@@ -27,12 +31,12 @@ class ExtendedTx:
|
||||
self.status_code = TxStatus.PENDING.value
|
||||
|
||||
|
||||
def set_actors(self, sender, recipient, trusted_declarator_addresses=None):
|
||||
def set_actors(self, sender, recipient, trusted_declarator_addresses=None, caller_address=ZERO_ADDRESS):
|
||||
self.sender = sender
|
||||
self.recipient = recipient
|
||||
if trusted_declarator_addresses != None:
|
||||
self.sender_label = translate_address(sender, trusted_declarator_addresses, self.chain_spec)
|
||||
self.recipient_label = translate_address(recipient, trusted_declarator_addresses, self.chain_spec)
|
||||
self.sender_label = translate_address(sender, trusted_declarator_addresses, self.chain_spec, sender_address=caller_address)
|
||||
self.recipient_label = translate_address(recipient, trusted_declarator_addresses, self.chain_spec, sender_address=caller_address)
|
||||
|
||||
|
||||
def set_tokens(self, source, source_value, destination=None, destination_value=None):
|
||||
@@ -40,8 +44,8 @@ class ExtendedTx:
|
||||
destination = source
|
||||
if destination_value == None:
|
||||
destination_value = source_value
|
||||
st = ERC20Token(self.rpc, source)
|
||||
dt = ERC20Token(self.rpc, destination)
|
||||
st = ERC20Token(self.chain_spec, self.rpc, source)
|
||||
dt = ERC20Token(self.chain_spec, self.rpc, destination)
|
||||
self.source_token = source
|
||||
self.source_token_symbol = st.symbol
|
||||
self.source_token_name = st.name
|
||||
|
||||
@@ -15,7 +15,6 @@ from cic_eth_registry import CICRegistry
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.tx import unpack
|
||||
from chainlib.connection import RPCConnection
|
||||
from chainsyncer.error import SyncDone
|
||||
from hexathon import strip_0x
|
||||
from chainqueue.db.enum import (
|
||||
StatusEnum,
|
||||
@@ -153,10 +152,7 @@ class DispatchSyncer:
|
||||
def main():
|
||||
syncer = DispatchSyncer(chain_spec)
|
||||
conn = RPCConnection.connect(chain_spec, 'default')
|
||||
try:
|
||||
syncer.loop(conn, float(config.get('DISPATCHER_LOOP_INTERVAL')))
|
||||
except SyncDone as e:
|
||||
sys.stderr.write("dispatcher done at block {}\n".format(e))
|
||||
syncer.loop(conn, float(config.get('DISPATCHER_LOOP_INTERVAL')))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
# external imports
|
||||
import celery
|
||||
from cic_eth_registry.error import UnknownContractError
|
||||
from chainlib.status import Status as TxStatus
|
||||
@@ -9,7 +9,13 @@ from chainlib.eth.address import to_checksum_address
|
||||
from chainlib.eth.error import RequestMismatchException
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.erc20 import ERC20
|
||||
from hexathon import strip_0x
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
add_0x,
|
||||
)
|
||||
# TODO: use sarafu_Faucet for both when inheritance has been implemented
|
||||
from erc20_single_shot_faucet import SingleShotFaucet
|
||||
from sarafu_faucet import MinterFaucet as Faucet
|
||||
|
||||
# local imports
|
||||
from .base import SyncFilter
|
||||
@@ -18,55 +24,63 @@ from cic_eth.eth.meta import ExtendedTx
|
||||
logg = logging.getLogger().getChild(__name__)
|
||||
|
||||
|
||||
def parse_transfer(tx):
|
||||
r = ERC20.parse_transfer_request(tx.payload)
|
||||
transfer_data = {}
|
||||
transfer_data['to'] = r[0]
|
||||
transfer_data['value'] = r[1]
|
||||
transfer_data['from'] = tx['from']
|
||||
transfer_data['token_address'] = tx['to']
|
||||
return ('transfer', transfer_data)
|
||||
|
||||
|
||||
def parse_transferfrom(tx):
|
||||
r = ERC20.parse_transfer_request(tx.payload)
|
||||
transfer_data = unpack_transferfrom(tx.payload)
|
||||
transfer_data['from'] = r[0]
|
||||
transfer_data['to'] = r[1]
|
||||
transfer_data['value'] = r[2]
|
||||
transfer_data['token_address'] = tx['to']
|
||||
return ('transferfrom', transfer_data)
|
||||
|
||||
|
||||
def parse_giftto(tx):
|
||||
# TODO: broken
|
||||
logg.error('broken')
|
||||
return
|
||||
transfer_data = unpack_gift(tx.payload)
|
||||
transfer_data['from'] = tx.inputs[0]
|
||||
transfer_data['value'] = 0
|
||||
transfer_data['token_address'] = ZERO_ADDRESS
|
||||
# TODO: would be better to query the gift amount from the block state
|
||||
for l in tx.logs:
|
||||
topics = l['topics']
|
||||
logg.debug('topixx {}'.format(topics))
|
||||
if strip_0x(topics[0]) == '45c201a59ac545000ead84f30b2db67da23353aa1d58ac522c48505412143ffa':
|
||||
#transfer_data['value'] = web3.Web3.toInt(hexstr=strip_0x(l['data']))
|
||||
transfer_data['value'] = int.from_bytes(bytes.fromhex(strip_0x(l_data)))
|
||||
#token_address_bytes = topics[2][32-20:]
|
||||
token_address = strip_0x(topics[2])[64-40:]
|
||||
transfer_data['token_address'] = to_checksum_address(token_address)
|
||||
return ('tokengift', transfer_data)
|
||||
|
||||
|
||||
class CallbackFilter(SyncFilter):
|
||||
|
||||
trusted_addresses = []
|
||||
|
||||
def __init__(self, chain_spec, method, queue):
|
||||
def __init__(self, chain_spec, method, queue, caller_address=ZERO_ADDRESS):
|
||||
self.queue = queue
|
||||
self.method = method
|
||||
self.chain_spec = chain_spec
|
||||
self.caller_address = caller_address
|
||||
|
||||
|
||||
def parse_transfer(self, tx, conn):
|
||||
if not tx.payload:
|
||||
return (None, None)
|
||||
r = ERC20.parse_transfer_request(tx.payload)
|
||||
transfer_data = {}
|
||||
transfer_data['to'] = r[0]
|
||||
transfer_data['value'] = r[1]
|
||||
transfer_data['from'] = tx.outputs[0]
|
||||
transfer_data['token_address'] = tx.inputs[0]
|
||||
return ('transfer', transfer_data)
|
||||
|
||||
|
||||
def parse_transferfrom(self, tx, conn):
|
||||
if not tx.payload:
|
||||
return (None, None)
|
||||
r = ERC20.parse_transfer_from_request(tx.payload)
|
||||
transfer_data = {}
|
||||
transfer_data['from'] = r[0]
|
||||
transfer_data['to'] = r[1]
|
||||
transfer_data['value'] = r[2]
|
||||
transfer_data['token_address'] = tx.inputs[0]
|
||||
return ('transferfrom', transfer_data)
|
||||
|
||||
|
||||
def parse_giftto(self, tx, conn):
|
||||
if not tx.payload:
|
||||
return (None, None)
|
||||
r = Faucet.parse_give_to_request(tx.payload)
|
||||
transfer_data = {}
|
||||
transfer_data['to'] = r[0]
|
||||
transfer_data['value'] = tx.value
|
||||
transfer_data['from'] = tx.outputs[0]
|
||||
#transfer_data['token_address'] = tx.inputs[0]
|
||||
faucet_contract = tx.inputs[0]
|
||||
|
||||
c = SingleShotFaucet(self.chain_spec)
|
||||
o = c.token(faucet_contract, sender_address=self.caller_address)
|
||||
r = conn.do(o)
|
||||
transfer_data['token_address'] = add_0x(c.parse_token(r))
|
||||
|
||||
o = c.amount(faucet_contract, sender_address=self.caller_address)
|
||||
r = conn.do(o)
|
||||
transfer_data['amount'] = add_0x(c.parse_amount(r))
|
||||
|
||||
return ('tokengift', transfer_data)
|
||||
|
||||
|
||||
def call_back(self, transfer_type, result):
|
||||
@@ -95,23 +109,26 @@ class CallbackFilter(SyncFilter):
|
||||
return s
|
||||
|
||||
|
||||
def parse_data(self, tx):
|
||||
def parse_data(self, tx, conn):
|
||||
transfer_type = None
|
||||
transfer_data = None
|
||||
# TODO: what's with the mix of attributes and dict keys
|
||||
logg.debug('have payload {}'.format(tx.payload))
|
||||
method_signature = tx.payload[:8]
|
||||
|
||||
logg.debug('tx status {}'.format(tx.status))
|
||||
|
||||
for parser in [
|
||||
parse_transfer,
|
||||
parse_transferfrom,
|
||||
parse_giftto,
|
||||
self.parse_transfer,
|
||||
self.parse_transferfrom,
|
||||
self.parse_giftto,
|
||||
]:
|
||||
try:
|
||||
(transfer_type, transfer_data) = parser(tx)
|
||||
break
|
||||
if tx:
|
||||
(transfer_type, transfer_data) = parser(tx, conn)
|
||||
if transfer_type == None:
|
||||
continue
|
||||
else:
|
||||
pass
|
||||
except RequestMismatchException:
|
||||
continue
|
||||
|
||||
@@ -128,7 +145,7 @@ class CallbackFilter(SyncFilter):
|
||||
transfer_data = None
|
||||
transfer_type = None
|
||||
try:
|
||||
(transfer_type, transfer_data) = self.parse_data(tx)
|
||||
(transfer_type, transfer_data) = self.parse_data(tx, conn)
|
||||
except TypeError:
|
||||
logg.debug('invalid method data length for tx {}'.format(tx.hash))
|
||||
return
|
||||
@@ -144,7 +161,7 @@ class CallbackFilter(SyncFilter):
|
||||
result = None
|
||||
try:
|
||||
tokentx = ExtendedTx(conn, tx.hash, self.chain_spec)
|
||||
tokentx.set_actors(transfer_data['from'], transfer_data['to'], self.trusted_addresses)
|
||||
tokentx.set_actors(transfer_data['from'], transfer_data['to'], self.trusted_addresses, caller_address=self.caller_address)
|
||||
tokentx.set_tokens(transfer_data['token_address'], transfer_data['value'])
|
||||
if transfer_data['status'] == 0:
|
||||
tokentx.set_status(1)
|
||||
@@ -153,7 +170,7 @@ class CallbackFilter(SyncFilter):
|
||||
t = self.call_back(transfer_type, tokentx.to_dict())
|
||||
logg.info('callback success task id {} tx {}'.format(t, tx.hash))
|
||||
except UnknownContractError:
|
||||
logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(tc.queue, tc.method, transfer_data['to'], tx.hash))
|
||||
logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(tx.queue, tx.method, transfer_data['to'], tx.hash))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -15,7 +15,6 @@ import cic_base.config
|
||||
import cic_base.log
|
||||
import cic_base.argparse
|
||||
import cic_base.rpc
|
||||
from cic_eth_registry import CICRegistry
|
||||
from cic_eth_registry.error import UnknownContractError
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
@@ -26,7 +25,7 @@ from chainlib.eth.block import (
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
)
|
||||
from chainsyncer.backend import SyncerBackend
|
||||
from chainsyncer.backend.sql import SQLBackend
|
||||
from chainsyncer.driver import (
|
||||
HeadSyncer,
|
||||
HistorySyncer,
|
||||
@@ -43,6 +42,12 @@ from cic_eth.runnable.daemons.filters import (
|
||||
TransferAuthFilter,
|
||||
)
|
||||
from cic_eth.stat import init_chain_stat
|
||||
from cic_eth.registry import (
|
||||
connect as connect_registry,
|
||||
connect_declarator,
|
||||
connect_token_registry,
|
||||
)
|
||||
|
||||
|
||||
script_dir = os.path.realpath(os.path.dirname(__file__))
|
||||
|
||||
@@ -88,18 +93,18 @@ def main():
|
||||
|
||||
syncers = []
|
||||
|
||||
#if SyncerBackend.first(chain_spec):
|
||||
# backend = SyncerBackend.initial(chain_spec, block_offset)
|
||||
syncer_backends = SyncerBackend.resume(chain_spec, block_offset)
|
||||
#if SQLBackend.first(chain_spec):
|
||||
# backend = SQLBackend.initial(chain_spec, block_offset)
|
||||
syncer_backends = SQLBackend.resume(chain_spec, block_offset)
|
||||
|
||||
if len(syncer_backends) == 0:
|
||||
logg.info('found no backends to resume')
|
||||
syncer_backends.append(SyncerBackend.initial(chain_spec, block_offset))
|
||||
syncer_backends.append(SQLBackend.initial(chain_spec, block_offset))
|
||||
else:
|
||||
for syncer_backend in syncer_backends:
|
||||
logg.info('resuming sync session {}'.format(syncer_backend))
|
||||
|
||||
syncer_backends.append(SyncerBackend.live(chain_spec, block_offset+1))
|
||||
syncer_backends.append(SQLBackend.live(chain_spec, block_offset+1))
|
||||
|
||||
for syncer_backend in syncer_backends:
|
||||
try:
|
||||
@@ -109,6 +114,8 @@ def main():
|
||||
logg.info('Initializing HEAD syncer on backend {}'.format(syncer_backend))
|
||||
syncers.append(HeadSyncer(syncer_backend))
|
||||
|
||||
connect_registry(rpc, chain_spec, config.get('CIC_REGISTRY_ADDRESS'))
|
||||
|
||||
trusted_addresses_src = config.get('CIC_TRUST_ADDRESS')
|
||||
if trusted_addresses_src == None:
|
||||
logg.critical('At least one trusted address must be declared in CIC_TRUST_ADDRESS')
|
||||
@@ -116,6 +123,8 @@ def main():
|
||||
trusted_addresses = trusted_addresses_src.split(',')
|
||||
for address in trusted_addresses:
|
||||
logg.info('using trusted address {}'.format(address))
|
||||
connect_declarator(rpc, chain_spec, trusted_addresses)
|
||||
connect_token_registry(rpc, chain_spec)
|
||||
CallbackFilter.trusted_addresses = trusted_addresses
|
||||
|
||||
callback_filters = []
|
||||
|
||||
@@ -4,7 +4,7 @@ import datetime
|
||||
|
||||
# external imports
|
||||
from chainsyncer.driver import HeadSyncer
|
||||
from chainsyncer.backend import MemBackend
|
||||
from chainsyncer.backend.memory import MemBackend
|
||||
from chainsyncer.error import NoBlockForYou
|
||||
from chainlib.eth.block import (
|
||||
block_by_number,
|
||||
|
||||
@@ -10,7 +10,7 @@ version = (
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
'beta.3',
|
||||
'beta.6',
|
||||
)
|
||||
|
||||
version_object = semver.VersionInfo(
|
||||
|
||||
@@ -29,7 +29,7 @@ RUN /usr/local/bin/python -m pip install --upgrade pip
|
||||
# python merge_requirements.py | tee merged_requirements.txt
|
||||
#RUN cd cic-base && \
|
||||
# pip install $pip_extra_index_url_flag -r ./merged_requirements.txt
|
||||
RUN pip install $pip_extra_index_url_flag cic-base[full_graph]==0.1.2a62
|
||||
RUN pip install $pip_extra_index_url_flag cic-base[full_graph]==0.1.2a77
|
||||
|
||||
COPY cic-eth/scripts/ scripts/
|
||||
COPY cic-eth/setup.cfg cic-eth/setup.py ./
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
cic-base~=0.1.2a67
|
||||
cic-base~=0.1.2a76
|
||||
celery==4.4.7
|
||||
crypto-dev-signer~=0.4.14a17
|
||||
crypto-dev-signer~=0.4.14b2
|
||||
confini~=0.3.6rc3
|
||||
cic-eth-registry~=0.5.4a13
|
||||
cic-eth-registry~=0.5.4a16
|
||||
#cic-bancor~=0.0.6
|
||||
redis==3.5.3
|
||||
alembic==1.4.2
|
||||
websockets==8.1
|
||||
requests~=2.24.0
|
||||
eth_accounts_index~=0.0.11a7
|
||||
erc20-transfer-authorization~=0.3.1a3
|
||||
#simple-rlp==0.1.2
|
||||
eth_accounts_index~=0.0.11a9
|
||||
erc20-transfer-authorization~=0.3.1a5
|
||||
uWSGI==2.0.19.1
|
||||
semver==2.13.0
|
||||
websocket-client==0.57.0
|
||||
moolb~=0.1.1b2
|
||||
eth-address-index~=0.1.1a7
|
||||
chainlib~=0.0.2a5
|
||||
eth-address-index~=0.1.1a9
|
||||
chainlib~=0.0.2a13
|
||||
hexathon~=0.0.1a7
|
||||
chainsyncer[sql]~=0.0.2a1
|
||||
chainsyncer[sql]~=0.0.2a2
|
||||
chainqueue~=0.0.1a7
|
||||
pysha3==1.0.2
|
||||
coincurve==15.0.0
|
||||
sarafu-faucet~=0.0.2a19
|
||||
sarafu-faucet==0.0.2a28
|
||||
potaahto~=0.0.1a1
|
||||
|
||||
@@ -4,4 +4,4 @@ pytest-mock==3.3.1
|
||||
pytest-cov==2.10.1
|
||||
eth-tester==0.5.0b3
|
||||
py-evm==0.3.0a20
|
||||
giftable-erc20-token==0.0.8a4
|
||||
giftable-erc20-token==0.0.8a9
|
||||
|
||||
223
apps/cic-eth/tests/filters/test_callback_filter.py
Normal file
223
apps/cic-eth/tests/filters/test_callback_filter.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# standard import
|
||||
import logging
|
||||
import datetime
|
||||
import os
|
||||
|
||||
# external imports
|
||||
import pytest
|
||||
from chainlib.connection import RPCConnection
|
||||
from chainlib.eth.nonce import RPCNonceOracle
|
||||
from chainlib.eth.gas import OverrideGasOracle
|
||||
from chainlib.eth.tx import (
|
||||
receipt,
|
||||
transaction,
|
||||
Tx,
|
||||
)
|
||||
from chainlib.eth.block import Block
|
||||
from chainlib.eth.erc20 import ERC20
|
||||
from sarafu_faucet import MinterFaucet
|
||||
from eth_accounts_index import AccountRegistry
|
||||
from potaahto.symbols import snake_and_camel
|
||||
from hexathon import add_0x
|
||||
|
||||
# local imports
|
||||
from cic_eth.runnable.daemons.filters.callback import CallbackFilter
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
@pytest.mark.skip()
|
||||
def test_transfer_tx(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
eth_rpc,
|
||||
eth_signer,
|
||||
foo_token,
|
||||
agent_roles,
|
||||
token_roles,
|
||||
contract_roles,
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
rpc = RPCConnection.connect(default_chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], rpc)
|
||||
gas_oracle = OverrideGasOracle(conn=rpc, limit=200000)
|
||||
|
||||
txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
(tx_hash_hex, o) = txf.transfer(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], 1024)
|
||||
r = rpc.do(o)
|
||||
|
||||
o = transaction(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
logg.debug(r)
|
||||
tx_src = snake_and_camel(r)
|
||||
tx = Tx(tx_src)
|
||||
|
||||
o = receipt(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
assert r['status'] == 1
|
||||
|
||||
rcpt = snake_and_camel(r)
|
||||
tx.apply_receipt(rcpt)
|
||||
|
||||
fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER'])
|
||||
(transfer_type, transfer_data) = fltr.parse_transfer(tx, eth_rpc)
|
||||
|
||||
assert transfer_type == 'transfer'
|
||||
|
||||
|
||||
@pytest.mark.skip()
|
||||
def test_transfer_from_tx(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
eth_rpc,
|
||||
eth_signer,
|
||||
foo_token,
|
||||
agent_roles,
|
||||
token_roles,
|
||||
contract_roles,
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
rpc = RPCConnection.connect(default_chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], rpc)
|
||||
gas_oracle = OverrideGasOracle(conn=rpc, limit=200000)
|
||||
|
||||
txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
|
||||
(tx_hash_hex, o) = txf.approve(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], 1024)
|
||||
r = rpc.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
assert r['status'] == 1
|
||||
|
||||
nonce_oracle = RPCNonceOracle(agent_roles['ALICE'], rpc)
|
||||
txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
(tx_hash_hex, o) = txf.transfer_from(foo_token, agent_roles['ALICE'], token_roles['FOO_TOKEN_OWNER'], agent_roles['BOB'], 1024)
|
||||
r = rpc.do(o)
|
||||
|
||||
o = transaction(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
tx_src = snake_and_camel(r)
|
||||
tx = Tx(tx_src)
|
||||
|
||||
o = receipt(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
assert r['status'] == 1
|
||||
|
||||
rcpt = snake_and_camel(r)
|
||||
tx.apply_receipt(rcpt)
|
||||
|
||||
fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER'])
|
||||
(transfer_type, transfer_data) = fltr.parse_transferfrom(tx, eth_rpc)
|
||||
|
||||
assert transfer_type == 'transferfrom'
|
||||
|
||||
|
||||
def test_faucet_gift_to_tx(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
eth_rpc,
|
||||
eth_signer,
|
||||
foo_token,
|
||||
agent_roles,
|
||||
contract_roles,
|
||||
faucet,
|
||||
account_registry,
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
rpc = RPCConnection.connect(default_chain_spec, 'default')
|
||||
gas_oracle = OverrideGasOracle(conn=rpc, limit=800000)
|
||||
|
||||
nonce_oracle = RPCNonceOracle(contract_roles['ACCOUNT_REGISTRY_WRITER'], rpc)
|
||||
txf = AccountRegistry(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
(tx_hash_hex, o) = txf.add(account_registry, contract_roles['ACCOUNT_REGISTRY_WRITER'], agent_roles['ALICE'])
|
||||
r = rpc.do(o)
|
||||
o = receipt(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
assert r['status'] == 1
|
||||
|
||||
nonce_oracle = RPCNonceOracle(agent_roles['ALICE'], rpc)
|
||||
txf = MinterFaucet(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
(tx_hash_hex, o) = txf.give_to(faucet, agent_roles['ALICE'], agent_roles['ALICE'])
|
||||
r = rpc.do(o)
|
||||
|
||||
o = transaction(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
tx_src = snake_and_camel(r)
|
||||
tx = Tx(tx_src)
|
||||
|
||||
o = receipt(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
assert r['status'] == 1
|
||||
|
||||
rcpt = snake_and_camel(r)
|
||||
tx.apply_receipt(rcpt)
|
||||
|
||||
fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER'])
|
||||
(transfer_type, transfer_data) = fltr.parse_giftto(tx, eth_rpc)
|
||||
|
||||
assert transfer_type == 'tokengift'
|
||||
assert transfer_data['token_address'] == foo_token
|
||||
|
||||
|
||||
def test_callback_filter(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
eth_rpc,
|
||||
eth_signer,
|
||||
foo_token,
|
||||
token_roles,
|
||||
agent_roles,
|
||||
contract_roles,
|
||||
register_lookups,
|
||||
):
|
||||
|
||||
rpc = RPCConnection.connect(default_chain_spec, 'default')
|
||||
nonce_oracle = RPCNonceOracle(token_roles['FOO_TOKEN_OWNER'], rpc)
|
||||
gas_oracle = OverrideGasOracle(conn=rpc, limit=200000)
|
||||
|
||||
txf = ERC20(default_chain_spec, signer=eth_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
(tx_hash_hex, o) = txf.transfer(foo_token, token_roles['FOO_TOKEN_OWNER'], agent_roles['ALICE'], 1024)
|
||||
r = rpc.do(o)
|
||||
|
||||
o = transaction(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
logg.debug(r)
|
||||
|
||||
mockblock_src = {
|
||||
'hash': add_0x(os.urandom(32).hex()),
|
||||
'number': '0x2a',
|
||||
'transactions': [tx_hash_hex],
|
||||
'timestamp': datetime.datetime.utcnow().timestamp(),
|
||||
}
|
||||
mockblock = Block(mockblock_src)
|
||||
|
||||
tx_src = snake_and_camel(r)
|
||||
tx = Tx(tx_src, block=mockblock)
|
||||
|
||||
o = receipt(tx_hash_hex)
|
||||
r = rpc.do(o)
|
||||
assert r['status'] == 1
|
||||
|
||||
rcpt = snake_and_camel(r)
|
||||
tx.apply_receipt(rcpt)
|
||||
|
||||
fltr = CallbackFilter(default_chain_spec, None, None, caller_address=contract_roles['CONTRACT_DEPLOYER'])
|
||||
|
||||
class CallbackMock:
|
||||
|
||||
def __init__(self):
|
||||
self.results = {}
|
||||
|
||||
def call_back(self, transfer_type, result):
|
||||
self.results[transfer_type] = result
|
||||
|
||||
mock = CallbackMock()
|
||||
fltr.call_back = mock.call_back
|
||||
|
||||
fltr.filter(eth_rpc, mockblock, tx, init_database)
|
||||
|
||||
assert mock.results.get('transfer') != None
|
||||
assert mock.results['transfer']['destination_token'] == foo_token
|
||||
@@ -1,7 +1,126 @@
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, Union
|
||||
|
||||
# third-part imports
|
||||
import requests
|
||||
from cic_types.models.person import generate_metadata_pointer, Person
|
||||
|
||||
# local imports
|
||||
from cic_ussd.metadata import make_request
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.redis import cache_data
|
||||
from cic_ussd.error import MetadataStoreError
|
||||
|
||||
|
||||
logg = logging.getLogger().getChild(__name__)
|
||||
|
||||
|
||||
class Metadata:
|
||||
"""
|
||||
:cvar base_url:
|
||||
:type base_url:
|
||||
:cvar base_url: The base url or the metadata server.
|
||||
:type base_url: str
|
||||
"""
|
||||
|
||||
base_url = None
|
||||
|
||||
|
||||
def metadata_http_error_handler(result: requests.Response):
|
||||
""" This function handles and appropriately raises errors from http requests interacting with the metadata server.
|
||||
:param result: The response object from a http request.
|
||||
:type result: requests.Response
|
||||
"""
|
||||
status_code = result.status_code
|
||||
|
||||
if 100 <= status_code < 200:
|
||||
raise MetadataStoreError(f'Informational errors: {status_code}, reason: {result.reason}')
|
||||
|
||||
elif 300 <= status_code < 400:
|
||||
raise MetadataStoreError(f'Redirect Issues: {status_code}, reason: {result.reason}')
|
||||
|
||||
elif 400 <= status_code < 500:
|
||||
raise MetadataStoreError(f'Client Error: {status_code}, reason: {result.reason}')
|
||||
|
||||
elif 500 <= status_code < 600:
|
||||
raise MetadataStoreError(f'Server Error: {status_code}, reason: {result.reason}')
|
||||
|
||||
|
||||
class MetadataRequestsHandler(Metadata):
|
||||
|
||||
def __init__(self, cic_type: str, identifier: bytes, engine: str = 'pgp'):
|
||||
"""
|
||||
:param cic_type: The salt value with which to hash a specific metadata identifier.
|
||||
:type cic_type: str
|
||||
:param engine: Encryption used for sending data to the metadata server.
|
||||
:type engine: str
|
||||
:param identifier: A unique element of data in bytes necessary for creating a metadata pointer.
|
||||
:type identifier: bytes
|
||||
"""
|
||||
self.cic_type = cic_type
|
||||
self.engine = engine
|
||||
self.headers = {
|
||||
'X-CIC-AUTOMERGE': 'server',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.identifier = identifier
|
||||
self.metadata_pointer = generate_metadata_pointer(
|
||||
identifier=self.identifier,
|
||||
cic_type=self.cic_type
|
||||
)
|
||||
if self.base_url:
|
||||
self.url = os.path.join(self.base_url, self.metadata_pointer)
|
||||
|
||||
def create(self, data: Union[Dict, str]):
|
||||
""" This function is responsible for posting data to the metadata server with a corresponding metadata pointer
|
||||
for storage.
|
||||
:param data: The data to be stored in the metadata server.
|
||||
:type data: dict|str
|
||||
"""
|
||||
data = json.dumps(data).encode('utf-8')
|
||||
result = make_request(method='POST', url=self.url, data=data, headers=self.headers)
|
||||
metadata_http_error_handler(result=result)
|
||||
metadata = result.content
|
||||
self.edit(data=metadata)
|
||||
|
||||
def edit(self, data: bytes):
|
||||
""" This function is responsible for editing data in the metadata server corresponding to a unique pointer.
|
||||
:param data: The data to be edited in the metadata server.
|
||||
:type data: bytes
|
||||
"""
|
||||
cic_meta_signer = Signer()
|
||||
signature = cic_meta_signer.sign_digest(data=data)
|
||||
algorithm = cic_meta_signer.get_operational_key().get('algo')
|
||||
decoded_data = data.decode('utf-8')
|
||||
formatted_data = {
|
||||
'm': data.decode('utf-8'),
|
||||
's': {
|
||||
'engine': self.engine,
|
||||
'algo': algorithm,
|
||||
'data': signature,
|
||||
'digest': json.loads(data).get('digest'),
|
||||
}
|
||||
}
|
||||
formatted_data = json.dumps(formatted_data).encode('utf-8')
|
||||
result = make_request(method='PUT', url=self.url, data=formatted_data, headers=self.headers)
|
||||
logg.info(f'signed metadata submission status: {result.status_code}.')
|
||||
metadata_http_error_handler(result=result)
|
||||
try:
|
||||
decoded_identifier = self.identifier.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
decoded_identifier = self.identifier.hex()
|
||||
logg.info(f'identifier: {decoded_identifier}. metadata pointer: {self.metadata_pointer} set to: {decoded_data}.')
|
||||
|
||||
def query(self):
|
||||
"""This function is responsible for querying the metadata server for data corresponding to a unique pointer."""
|
||||
result = make_request(method='GET', url=self.url)
|
||||
metadata_http_error_handler(result=result)
|
||||
response_data = result.content
|
||||
data = json.loads(response_data.decode('utf-8'))
|
||||
if result.status_code == 200 and self.cic_type == 'cic.person':
|
||||
person = Person()
|
||||
deserialized_person = person.deserialize(person_data=json.loads(data))
|
||||
data = json.dumps(deserialized_person.serialize())
|
||||
cache_data(self.metadata_pointer, data=data)
|
||||
logg.debug(f'caching: {data} with key: {self.metadata_pointer}')
|
||||
|
||||
12
apps/cic-ussd/cic_ussd/metadata/person.py
Normal file
12
apps/cic-ussd/cic_ussd/metadata/person.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# standard imports
|
||||
|
||||
# third-party imports
|
||||
|
||||
# local imports
|
||||
from .base import MetadataRequestsHandler
|
||||
|
||||
|
||||
class PersonMetadata(MetadataRequestsHandler):
|
||||
|
||||
def __init__(self, identifier: bytes):
|
||||
super().__init__(cic_type='cic.person', identifier=identifier)
|
||||
@@ -1,85 +1,13 @@
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
# external imports
|
||||
import requests
|
||||
from cic_types.models.person import generate_metadata_pointer
|
||||
from cic_ussd.metadata import make_request
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
|
||||
# local imports
|
||||
from cic_ussd.error import MetadataStoreError
|
||||
from .base import Metadata
|
||||
|
||||
logg = logging.getLogger().getChild(__name__)
|
||||
from .base import MetadataRequestsHandler
|
||||
|
||||
|
||||
class PhonePointerMetadata(Metadata):
|
||||
|
||||
def __init__(self, identifier: bytes, engine: str):
|
||||
"""
|
||||
:param identifier:
|
||||
:type identifier:
|
||||
"""
|
||||
|
||||
self.headers = {
|
||||
'X-CIC-AUTOMERGE': 'server',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.identifier = identifier
|
||||
self.metadata_pointer = generate_metadata_pointer(
|
||||
identifier=self.identifier,
|
||||
cic_type=':cic.phone'
|
||||
)
|
||||
if self.base_url:
|
||||
self.url = os.path.join(self.base_url, self.metadata_pointer)
|
||||
|
||||
self.engine = engine
|
||||
|
||||
|
||||
def create(self, data: str):
|
||||
try:
|
||||
data = json.dumps(data).encode('utf-8')
|
||||
result = make_request(method='POST', url=self.url, data=data, headers=self.headers)
|
||||
metadata = result.content
|
||||
logg.debug('data {} meta {} resp {} stats {}'.format(data, metadata, result.reason, result.status_code))
|
||||
self.edit(data=metadata, engine=self.engine)
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise MetadataStoreError(error)
|
||||
|
||||
|
||||
def edit(self, data: bytes, engine: str):
|
||||
"""
|
||||
:param data:
|
||||
:type data:
|
||||
:param engine:
|
||||
:type engine:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
cic_meta_signer = Signer()
|
||||
signature = cic_meta_signer.sign_digest(data=data)
|
||||
algorithm = cic_meta_signer.get_operational_key().get('algo')
|
||||
decoded_data = data.decode('utf-8')
|
||||
formatted_data = {
|
||||
'm': decoded_data,
|
||||
's': {
|
||||
'engine': engine,
|
||||
'algo': algorithm,
|
||||
'data': signature,
|
||||
'digest': json.loads(data).get('digest'),
|
||||
}
|
||||
}
|
||||
formatted_data = json.dumps(formatted_data).encode('utf-8')
|
||||
|
||||
try:
|
||||
result = make_request(method='PUT', url=self.url, data=formatted_data, headers=self.headers)
|
||||
logg.debug(f'signed phone pointer metadata submission status: {result.status_code}.')
|
||||
result.raise_for_status()
|
||||
logg.info('phone {} metadata pointer {} set to {}'.format(self.identifier.decode('utf-8'), self.metadata_pointer, decoded_data))
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise MetadataStoreError(error)
|
||||
class PhonePointerMetadata(MetadataRequestsHandler):
|
||||
|
||||
def __init__(self, identifier: bytes):
|
||||
super().__init__(cic_type='cic.msisdn', identifier=identifier)
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
import requests
|
||||
from cic_types.models.person import generate_metadata_pointer, Person
|
||||
|
||||
# local imports
|
||||
from cic_ussd.chain import Chain
|
||||
from cic_ussd.metadata import make_request
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.redis import cache_data
|
||||
from cic_ussd.error import MetadataStoreError
|
||||
from .base import Metadata
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class UserMetadata(Metadata):
|
||||
|
||||
|
||||
def __init__(self, identifier: bytes):
|
||||
"""
|
||||
:param identifier:
|
||||
:type identifier:
|
||||
"""
|
||||
self.headers = {
|
||||
'X-CIC-AUTOMERGE': 'server',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.identifier = identifier
|
||||
self.metadata_pointer = generate_metadata_pointer(
|
||||
identifier=self.identifier,
|
||||
cic_type=':cic.person'
|
||||
)
|
||||
if self.base_url:
|
||||
self.url = os.path.join(self.base_url, self.metadata_pointer)
|
||||
|
||||
def create(self, data: dict):
|
||||
try:
|
||||
data = json.dumps(data).encode('utf-8')
|
||||
result = make_request(method='POST', url=self.url, data=data, headers=self.headers)
|
||||
metadata = result.content
|
||||
self.edit(data=metadata, engine='pgp')
|
||||
logg.info(f'Get sign material response status: {result.status_code}')
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise MetadataStoreError(error)
|
||||
|
||||
def edit(self, data: bytes, engine: str):
|
||||
"""
|
||||
:param data:
|
||||
:type data:
|
||||
:param engine:
|
||||
:type engine:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
cic_meta_signer = Signer()
|
||||
signature = cic_meta_signer.sign_digest(data=data)
|
||||
algorithm = cic_meta_signer.get_operational_key().get('algo')
|
||||
formatted_data = {
|
||||
'm': data.decode('utf-8'),
|
||||
's': {
|
||||
'engine': engine,
|
||||
'algo': algorithm,
|
||||
'data': signature,
|
||||
'digest': json.loads(data).get('digest'),
|
||||
}
|
||||
}
|
||||
formatted_data = json.dumps(formatted_data).encode('utf-8')
|
||||
|
||||
try:
|
||||
result = make_request(method='PUT', url=self.url, data=formatted_data, headers=self.headers)
|
||||
logg.debug(f'signed user metadata submission status: {result.status_code}.')
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise MetadataStoreError(error)
|
||||
|
||||
def query(self):
|
||||
result = make_request(method='GET', url=self.url)
|
||||
status = result.status_code
|
||||
logg.info(f'Get latest data status: {status}')
|
||||
try:
|
||||
if status == 200:
|
||||
response_data = result.content
|
||||
data = json.loads(response_data.decode())
|
||||
|
||||
# validate data
|
||||
person = Person()
|
||||
deserialized_person = person.deserialize(person_data=json.loads(data))
|
||||
|
||||
cache_data(key=self.metadata_pointer, data=json.dumps(deserialized_person.serialize()))
|
||||
elif status == 404:
|
||||
logg.info('The data is not available and might need to be added.')
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise MetadataNotFoundError(error)
|
||||
@@ -235,7 +235,7 @@ def process_display_user_metadata(user: User, display_key: str):
|
||||
products=products
|
||||
)
|
||||
else:
|
||||
raise MetadataNotFoundError(f'Expected user metadata but found none in cache for key: {user.blockchain_address}')
|
||||
raise MetadataNotFoundError(f'Expected person metadata but found none in cache for key: {key}')
|
||||
|
||||
|
||||
def process_account_statement(user: User, display_key: str, ussd_session: dict):
|
||||
@@ -331,11 +331,11 @@ def process_start_menu(display_key: str, user: User):
|
||||
operational_balance = compute_operational_balance(balances=balances_data)
|
||||
|
||||
# retrieve and cache account's metadata
|
||||
s_query_user_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.query_user_metadata',
|
||||
s_query_person_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.query_person_metadata',
|
||||
[blockchain_address]
|
||||
)
|
||||
s_query_user_metadata.apply_async(queue='cic-ussd')
|
||||
s_query_person_metadata.apply_async(queue='cic-ussd')
|
||||
|
||||
# retrieve and cache account's statement
|
||||
retrieve_account_statement(blockchain_address=blockchain_address)
|
||||
@@ -389,14 +389,11 @@ def process_request(user_input: str, user: User, ussd_session: Optional[dict] =
|
||||
identifier=blockchain_address_to_metadata_pointer(blockchain_address=user.blockchain_address),
|
||||
cic_type='cic.person'
|
||||
)
|
||||
logg.debug(f'METADATA POINTER: {key}')
|
||||
user_metadata = get_cached_data(key=key)
|
||||
logg.debug(f'METADATA: {user_metadata}')
|
||||
person_metadata = get_cached_data(key=key)
|
||||
|
||||
if last_ussd_session:
|
||||
# get last state
|
||||
last_state = last_ussd_session.state
|
||||
logg.debug(f'LAST USSD SESSION STATE: {last_state}')
|
||||
# if last state is account_creation_prompt and metadata exists, show start menu
|
||||
if last_state in [
|
||||
'account_creation_prompt',
|
||||
@@ -405,7 +402,7 @@ def process_request(user_input: str, user: User, ussd_session: Optional[dict] =
|
||||
'exit_invalid_new_pin',
|
||||
'exit_pin_mismatch',
|
||||
'exit_invalid_request'
|
||||
] and user_metadata is not None:
|
||||
] and person_metadata is not None:
|
||||
return UssdMenu.find_by_name(name='start')
|
||||
else:
|
||||
return UssdMenu.find_by_name(name=last_state)
|
||||
|
||||
@@ -97,11 +97,11 @@ def retrieve_recipient_metadata(state_machine_data: Tuple[str, dict, User]):
|
||||
recipient = get_user_by_phone_number(phone_number=user_input)
|
||||
blockchain_address = recipient.blockchain_address
|
||||
# retrieve and cache account's metadata
|
||||
s_query_user_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.query_user_metadata',
|
||||
s_query_person_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.query_person_metadata',
|
||||
[blockchain_address]
|
||||
)
|
||||
s_query_user_metadata.apply_async(queue='cic-ussd')
|
||||
s_query_person_metadata.apply_async(queue='cic-ussd')
|
||||
|
||||
|
||||
def save_transaction_amount_to_session_data(state_machine_data: Tuple[str, dict, User]):
|
||||
|
||||
@@ -164,11 +164,11 @@ def save_complete_user_metadata(state_machine_data: Tuple[str, dict, User]):
|
||||
user_metadata = format_user_metadata(metadata=metadata, user=user)
|
||||
|
||||
blockchain_address = user.blockchain_address
|
||||
s_create_user_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.create_user_metadata',
|
||||
s_create_person_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.create_person_metadata',
|
||||
[blockchain_address, user_metadata]
|
||||
)
|
||||
s_create_user_metadata.apply_async(queue='cic-ussd')
|
||||
s_create_person_metadata.apply_async(queue='cic-ussd')
|
||||
|
||||
|
||||
def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, User]):
|
||||
@@ -211,18 +211,18 @@ def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, User]):
|
||||
|
||||
edited_metadata = deserialized_person.serialize()
|
||||
|
||||
s_edit_user_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.edit_user_metadata',
|
||||
[blockchain_address, edited_metadata, 'pgp']
|
||||
s_edit_person_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.edit_person_metadata',
|
||||
[blockchain_address, edited_metadata]
|
||||
)
|
||||
s_edit_user_metadata.apply_async(queue='cic-ussd')
|
||||
s_edit_person_metadata.apply_async(queue='cic-ussd')
|
||||
|
||||
|
||||
def get_user_metadata(state_machine_data: Tuple[str, dict, User]):
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
blockchain_address = user.blockchain_address
|
||||
s_get_user_metadata = celery.signature(
|
||||
'cic_ussd.tasks.metadata.query_user_metadata',
|
||||
'cic_ussd.tasks.metadata.query_person_metadata',
|
||||
[blockchain_address]
|
||||
)
|
||||
s_get_user_metadata.apply_async(queue='cic-ussd')
|
||||
|
||||
@@ -57,14 +57,9 @@ def process_account_creation_callback(self, result: str, url: str, status_code:
|
||||
queue = self.request.delivery_info.get('routing_key')
|
||||
s = celery.signature(
|
||||
'cic_ussd.tasks.metadata.add_phone_pointer',
|
||||
[
|
||||
result,
|
||||
phone_number,
|
||||
'pgp',
|
||||
],
|
||||
queue=queue,
|
||||
[result, phone_number]
|
||||
)
|
||||
s.apply_async()
|
||||
s.apply_async(queue=queue)
|
||||
|
||||
# expire cache
|
||||
cache.expire(task_id, timedelta(seconds=180))
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
|
||||
# external imports
|
||||
# third-party imports
|
||||
import celery
|
||||
from hexathon import strip_0x
|
||||
|
||||
# local imports
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
from cic_ussd.metadata.user import UserMetadata
|
||||
from cic_ussd.metadata.person import PersonMetadata
|
||||
from cic_ussd.metadata.phone import PhonePointerMetadata
|
||||
from cic_ussd.tasks.base import CriticalMetadataTask
|
||||
|
||||
@@ -17,7 +16,7 @@ logg = logging.getLogger().getChild(__name__)
|
||||
|
||||
|
||||
@celery_app.task
|
||||
def query_user_metadata(blockchain_address: str):
|
||||
def query_person_metadata(blockchain_address: str):
|
||||
"""
|
||||
:param blockchain_address:
|
||||
:type blockchain_address:
|
||||
@@ -25,12 +24,12 @@ def query_user_metadata(blockchain_address: str):
|
||||
:rtype:
|
||||
"""
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
user_metadata_client.query()
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
person_metadata_client.query()
|
||||
|
||||
|
||||
@celery_app.task
|
||||
def create_user_metadata(blockchain_address: str, data: dict):
|
||||
def create_person_metadata(blockchain_address: str, data: dict):
|
||||
"""
|
||||
:param blockchain_address:
|
||||
:type blockchain_address:
|
||||
@@ -40,19 +39,20 @@ def create_user_metadata(blockchain_address: str, data: dict):
|
||||
:rtype:
|
||||
"""
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
user_metadata_client.create(data=data)
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
person_metadata_client.create(data=data)
|
||||
|
||||
|
||||
@celery_app.task
|
||||
def edit_user_metadata(blockchain_address: str, data: bytes, engine: str):
|
||||
def edit_person_metadata(blockchain_address: str, data: bytes):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
user_metadata_client.edit(data=data, engine=engine)
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
person_metadata_client.edit(data=data)
|
||||
|
||||
|
||||
@celery_app.task(bind=True, base=CriticalMetadataTask)
|
||||
def add_phone_pointer(self, blockchain_address: str, phone: str, engine: str):
|
||||
def add_phone_pointer(self, blockchain_address: str, phone_number: str):
|
||||
identifier = phone_number.encode('utf-8')
|
||||
stripped_address = strip_0x(blockchain_address)
|
||||
phone_metadata_client = PhonePointerMetadata(identifier=phone.encode('utf-8'), engine=engine)
|
||||
phone_metadata_client = PhonePointerMetadata(identifier=identifier)
|
||||
phone_metadata_client.create(data=stripped_address)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cic_base[full_graph]~=0.1.2a67
|
||||
cic_base[full_graph]~=0.1.2a68
|
||||
cic-eth~=0.11.0b3
|
||||
cic-notify~=0.4.0a3
|
||||
cic-types~=0.1.0a10
|
||||
|
||||
@@ -9,26 +9,26 @@ from cic_types.models.person import generate_metadata_pointer
|
||||
# local imports
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.metadata.user import UserMetadata
|
||||
from cic_ussd.metadata.person import PersonMetadata
|
||||
from cic_ussd.redis import get_cached_data
|
||||
|
||||
|
||||
def test_user_metadata(create_activated_user, define_metadata_pointer_url, load_config):
|
||||
UserMetadata.base_url = load_config.get('CIC_META_URL')
|
||||
PersonMetadata.base_url = load_config.get('CIC_META_URL')
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
|
||||
assert user_metadata_client.url == define_metadata_pointer_url
|
||||
assert person_metadata_client.url == define_metadata_pointer_url
|
||||
|
||||
|
||||
def test_create_user_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
load_config,
|
||||
mock_meta_post_response,
|
||||
person_metadata):
|
||||
def test_create_person_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
load_config,
|
||||
mock_meta_post_response,
|
||||
person_metadata):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
@@ -38,7 +38,7 @@ def test_create_user_metadata(caplog,
|
||||
reason='CREATED',
|
||||
content=json.dumps(mock_meta_post_response).encode('utf-8')
|
||||
)
|
||||
user_metadata_client.create(data=person_metadata)
|
||||
person_metadata_client.create(data=person_metadata)
|
||||
assert 'Get signed material response status: 201' in caplog.text
|
||||
|
||||
with pytest.raises(RuntimeError) as error:
|
||||
@@ -49,19 +49,19 @@ def test_create_user_metadata(caplog,
|
||||
status_code=400,
|
||||
reason='BAD REQUEST'
|
||||
)
|
||||
user_metadata_client.create(data=person_metadata)
|
||||
person_metadata_client.create(data=person_metadata)
|
||||
assert str(error.value) == f'400 Client Error: BAD REQUEST for url: {define_metadata_pointer_url}'
|
||||
|
||||
|
||||
def test_edit_user_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
load_config,
|
||||
person_metadata,
|
||||
setup_metadata_signer):
|
||||
def test_edit_person_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
load_config,
|
||||
person_metadata,
|
||||
setup_metadata_signer):
|
||||
Signer.gpg_passphrase = load_config.get('KEYS_PASSPHRASE')
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'PUT',
|
||||
@@ -69,7 +69,7 @@ def test_edit_user_metadata(caplog,
|
||||
status_code=200,
|
||||
reason='OK'
|
||||
)
|
||||
user_metadata_client.edit(data=person_metadata, engine='pgp')
|
||||
person_metadata_client.edit(data=person_metadata)
|
||||
assert 'Signed content submission status: 200' in caplog.text
|
||||
|
||||
with pytest.raises(RuntimeError) as error:
|
||||
@@ -80,7 +80,7 @@ def test_edit_user_metadata(caplog,
|
||||
status_code=400,
|
||||
reason='BAD REQUEST'
|
||||
)
|
||||
user_metadata_client.edit(data=person_metadata, engine='pgp')
|
||||
person_metadata_client.edit(data=person_metadata)
|
||||
assert str(error.value) == f'400 Client Error: BAD REQUEST for url: {define_metadata_pointer_url}'
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ def test_get_user_metadata(caplog,
|
||||
person_metadata,
|
||||
setup_metadata_signer):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'GET',
|
||||
@@ -101,7 +101,7 @@ def test_get_user_metadata(caplog,
|
||||
content=json.dumps(person_metadata).encode('utf-8'),
|
||||
reason='OK'
|
||||
)
|
||||
user_metadata_client.query()
|
||||
person_metadata_client.query()
|
||||
assert 'Get latest data status: 200' in caplog.text
|
||||
key = generate_metadata_pointer(
|
||||
identifier=identifier,
|
||||
@@ -118,6 +118,6 @@ def test_get_user_metadata(caplog,
|
||||
status_code=404,
|
||||
reason='NOT FOUND'
|
||||
)
|
||||
user_metadata_client.query()
|
||||
person_metadata_client.query()
|
||||
assert 'The data is not available and might need to be added.' in caplog.text
|
||||
assert str(error.value) == f'400 Client Error: NOT FOUND for url: {define_metadata_pointer_url}'
|
||||
|
||||
@@ -15,7 +15,7 @@ from cic_ussd.state_machine.logic.user import (
|
||||
get_user_metadata,
|
||||
save_complete_user_metadata,
|
||||
process_gender_user_input,
|
||||
save_profile_attribute_to_session_data,
|
||||
save_metadata_attribute_to_session_data,
|
||||
update_account_status_to_active)
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ def test_update_account_status_to_active(create_pending_user, create_in_db_ussd_
|
||||
("enter_location", "location", "Kangemi", "Kangemi"),
|
||||
("enter_products", "products", "Mandazi", "Mandazi"),
|
||||
])
|
||||
def test_save_save_profile_attribute_to_session_data(current_state,
|
||||
expected_key,
|
||||
expected_result,
|
||||
user_input,
|
||||
celery_session_worker,
|
||||
create_activated_user,
|
||||
create_in_db_ussd_session,
|
||||
create_in_redis_ussd_session):
|
||||
def test_save_metadata_attribute_to_session_data(current_state,
|
||||
expected_key,
|
||||
expected_result,
|
||||
user_input,
|
||||
celery_session_worker,
|
||||
create_activated_user,
|
||||
create_in_db_ussd_session,
|
||||
create_in_redis_ussd_session):
|
||||
create_in_db_ussd_session.state = current_state
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = (user_input, serialized_in_db_ussd_session, create_activated_user)
|
||||
@@ -56,7 +56,7 @@ def test_save_save_profile_attribute_to_session_data(current_state,
|
||||
in_memory_ussd_session = json.loads(in_memory_ussd_session)
|
||||
assert in_memory_ussd_session.get('session_data') == {}
|
||||
serialized_in_db_ussd_session['state'] = current_state
|
||||
save_profile_attribute_to_session_data(state_machine_data=state_machine_data)
|
||||
save_metadata_attribute_to_session_data(state_machine_data=state_machine_data)
|
||||
|
||||
in_memory_ussd_session = InMemoryStore.cache.get('AT974186')
|
||||
in_memory_ussd_session = json.loads(in_memory_ussd_session)
|
||||
@@ -87,18 +87,18 @@ def test_format_user_metadata(create_activated_user,
|
||||
|
||||
|
||||
def test_save_complete_user_metadata(celery_session_worker,
|
||||
complete_user_metadata,
|
||||
create_activated_user,
|
||||
create_in_redis_ussd_session,
|
||||
mocker,
|
||||
setup_chain_spec,
|
||||
ussd_session_data):
|
||||
complete_user_metadata,
|
||||
create_activated_user,
|
||||
create_in_redis_ussd_session,
|
||||
mocker,
|
||||
setup_chain_spec,
|
||||
ussd_session_data):
|
||||
ussd_session = create_in_redis_ussd_session.get(ussd_session_data.get('external_session_id'))
|
||||
ussd_session = json.loads(ussd_session)
|
||||
ussd_session['session_data'] = complete_user_metadata
|
||||
user_metadata = format_user_metadata(metadata=ussd_session.get('session_data'), user=create_activated_user)
|
||||
state_machine_data = ('', ussd_session, create_activated_user)
|
||||
mocked_create_metadata_task = mocker.patch('cic_ussd.tasks.metadata.create_user_metadata.apply_async')
|
||||
mocked_create_metadata_task = mocker.patch('cic_ussd.tasks.metadata.create_person_metadata.apply_async')
|
||||
save_complete_user_metadata(state_machine_data=state_machine_data)
|
||||
mocked_create_metadata_task.assert_called_with(
|
||||
(user_metadata, create_activated_user.blockchain_address),
|
||||
@@ -127,7 +127,7 @@ def test_edit_user_metadata_attribute(celery_session_worker,
|
||||
}
|
||||
state_machine_data = ('', ussd_session, create_activated_user)
|
||||
|
||||
mocked_edit_metadata = mocker.patch('cic_ussd.tasks.metadata.edit_user_metadata.apply_async')
|
||||
mocked_edit_metadata = mocker.patch('cic_ussd.tasks.metadata.edit_person_metadata.apply_async')
|
||||
edit_user_metadata_attribute(state_machine_data=state_machine_data)
|
||||
person_metadata['location']['area_name'] = 'nairobi'
|
||||
mocked_edit_metadata.assert_called_with(
|
||||
@@ -146,7 +146,7 @@ def test_get_user_metadata_attribute(celery_session_worker,
|
||||
ussd_session = json.loads(ussd_session)
|
||||
state_machine_data = ('', ussd_session, create_activated_user)
|
||||
|
||||
mocked_get_metadata = mocker.patch('cic_ussd.tasks.metadata.query_user_metadata.apply_async')
|
||||
mocked_get_metadata = mocker.patch('cic_ussd.tasks.metadata.query_person_metadata.apply_async')
|
||||
get_user_metadata(state_machine_data=state_machine_data)
|
||||
mocked_get_metadata.assert_called_with(
|
||||
(create_activated_user.blockchain_address,),
|
||||
|
||||
8
apps/cic-ussd/tests/fixtures/config.py
vendored
8
apps/cic-ussd/tests/fixtures/config.py
vendored
@@ -18,7 +18,7 @@ from cic_ussd.files.local_files import create_local_file_data_stores, json_file_
|
||||
from cic_ussd.menu.ussd_menu import UssdMenu
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.metadata.user import UserMetadata
|
||||
from cic_ussd.metadata.person import PersonMetadata
|
||||
from cic_ussd.state_machine import UssdStateMachine
|
||||
|
||||
|
||||
@@ -121,9 +121,9 @@ def setup_metadata_signer(load_config):
|
||||
@pytest.fixture(scope='function')
|
||||
def define_metadata_pointer_url(load_config, create_activated_user):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
UserMetadata.base_url = load_config.get('CIC_META_URL')
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
return user_metadata_client.url
|
||||
PersonMetadata.base_url = load_config.get('CIC_META_URL')
|
||||
person_metadata_client = PersonMetadata(identifier=identifier)
|
||||
return person_metadata_client.url
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
|
||||
@@ -57,9 +57,9 @@ WORKDIR /home/grassroots
|
||||
USER grassroots
|
||||
|
||||
ARG pip_extra_index_url=https://pip.grassrootseconomics.net:8433
|
||||
ARG cic_base_version=0.1.2a68
|
||||
ARG cic_eth_version=0.11.0b3
|
||||
ARG sarafu_faucet_version=0.0.2a20
|
||||
ARG cic_base_version=0.1.2a77
|
||||
ARG cic_eth_version=0.11.0b6
|
||||
ARG sarafu_faucet_version=0.0.2a28
|
||||
ARG cic_contracts_version=0.0.2a2
|
||||
RUN pip install --user --extra-index-url $pip_extra_index_url cic-base[full_graph]==$cic_base_version \
|
||||
cic-eth==$cic_eth_version \
|
||||
|
||||
@@ -7,17 +7,12 @@ DEV_ETH_ACCOUNT_RESERVE_MINTER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUN
|
||||
DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
|
||||
DEV_RESERVE_AMOUNT=${DEV_ETH_RESERVE_AMOUNT:-""10000000000000000000000000000000000}
|
||||
faucet_amount=${DEV_FAUCET_AMOUNT:-0}
|
||||
keystore_file=$()
|
||||
DEV_ETH_KEYSTORE_FILE=${DEV_KEYSTORE_FILE:-`realpath ./keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c`}
|
||||
DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER=`eth-checksum 0x$(cat $DEV_ETH_KEYSTORE_FILE | jq -r .address)`
|
||||
|
||||
keystore_file=$(realpath ./keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c)
|
||||
|
||||
echo "environment:"
|
||||
printenv
|
||||
echo \n
|
||||
|
||||
echo "using wallet address $DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER"
|
||||
exit 0
|
||||
# This is a grassroots team convention for building the Bancor contracts using the bancor protocol repository truffle setup
|
||||
# Running this in docker-internal dev container (built from Docker folder in this repo) will write a
|
||||
# source-able env file to CIC_DATA_DIR. Services dependent on these contracts can mount this file OR
|
||||
|
||||
@@ -17,7 +17,7 @@ from hexathon import (
|
||||
strip_0x,
|
||||
add_0x,
|
||||
)
|
||||
from chainsyncer.backend import MemBackend
|
||||
from chainsyncer.backend.memory import MemBackend
|
||||
from chainsyncer.driver import HeadSyncer
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.block import (
|
||||
|
||||
@@ -17,7 +17,7 @@ from hexathon import (
|
||||
strip_0x,
|
||||
add_0x,
|
||||
)
|
||||
from chainsyncer.backend import MemBackend
|
||||
from chainsyncer.backend.memory import MemBackend
|
||||
from chainsyncer.driver import HeadSyncer
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.block import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cic-base[full_graph]==0.1.2a67
|
||||
sarafu-faucet==0.0.2a20
|
||||
cic-eth==0.11.0b3
|
||||
cic-base[full_graph]==0.1.2a77
|
||||
sarafu-faucet==0.0.2a28
|
||||
cic-eth==0.11.0b6
|
||||
cic-types==0.1.0a10
|
||||
crypto-dev-signer==0.4.14b1
|
||||
crypto-dev-signer==0.4.14b2
|
||||
|
||||
@@ -145,7 +145,7 @@ services:
|
||||
- -c
|
||||
- |
|
||||
if [[ -f /tmp/cic/config/.env ]]; then source /tmp/cic/config/.env; fi
|
||||
/usr/local/bin/cic-cache-trackerd -vv -c /usr/local/etc/cic-cache
|
||||
./start_tracker.sh -c /usr/local/etc/cic-cache -vv
|
||||
volumes:
|
||||
- contract-config:/tmp/cic/config/:ro
|
||||
|
||||
@@ -191,13 +191,13 @@ services:
|
||||
context: apps
|
||||
dockerfile: cic-cache/docker/Dockerfile
|
||||
environment:
|
||||
DATABASE_USER: $DATABASE_USER
|
||||
DATABASE_HOST: $DATABASE_HOST
|
||||
DATABASE_PORT: $DATABASE_PORT
|
||||
DATABASE_PASSWORD: $DATABASE_PASSWORD
|
||||
DATABASE_NAME: $DATABASE_NAME_CIC_CACHE
|
||||
DATABASE_USER: ${DATABASE_USER:-grassroots}
|
||||
DATABASE_HOST: ${DATABASE_HOST:-postgres}
|
||||
DATABASE_PORT: ${DATABASE_PORT:-5432}
|
||||
#DATABASE_PASSWORD: ${DATABASE_PASSWORD:-
|
||||
DATABASE_NAME: ${DATABASE_NAME_CIC_CACHE:-cic_cache}
|
||||
DATABASE_DEBUG: 1
|
||||
PGPASSWORD: $DATABASE_PASSWORD
|
||||
#PGPASSWORD: $DATABASE_PASSWORD
|
||||
SERVER_PORT: 8000
|
||||
ports:
|
||||
- ${HTTP_PORT_CIC_CACHE:-63313}:8000
|
||||
@@ -212,9 +212,10 @@ services:
|
||||
- |
|
||||
if [[ -f /tmp/cic/config/.env ]]; then source /tmp/cic/config/.env; fi
|
||||
"/usr/local/bin/uwsgi" \
|
||||
--wsgi-file /usr/src/cic-cache/cic_cache/runnable/serverd.py \
|
||||
--wsgi-file /usr/src/cic-cache/cic_cache/runnable/daemons/server.py \
|
||||
--http :8000 \
|
||||
--pyargv -vv
|
||||
--pyargv "-vv"
|
||||
|
||||
|
||||
cic-eth-tasker:
|
||||
# image: grassrootseconomics:cic-eth-service
|
||||
|
||||
Reference in New Issue
Block a user