Compare commits

..

11 Commits

Author SHA1 Message Date
nolash
b6fd47673d Update import scripts deps 2021-05-05 13:51:23 +02:00
nolash
450f69676a Update base in cic-eth 2021-05-05 13:49:24 +02:00
nolash
c951f4718e Clean up missing dependency change updates 2021-05-03 19:51:05 +02:00
nolash
9f7fd58142 Remove double sarafu-faucet requirement in cic-eth 2021-05-03 14:37:49 +02:00
nolash
bbfbd2051a Merge remote-tracking branch 'origin/master' into lash/cache-faucet 2021-05-03 14:10:28 +02:00
nolash
6764d6dd4b Update module names in verify, balance import 2021-05-03 13:58:15 +02:00
nolash
fcfb89e1e4 Update cic-types 2021-05-03 12:55:50 +02:00
nolash
1b9cf373f5 Merge remote-tracking branch 'origin/master' into lash/cache-faucet 2021-05-02 19:48:01 +02:00
nolash
38f1373b4c Merge remote-tracking branch 'origin/master' into lash/cache-faucet 2021-05-02 19:12:03 +02:00
nolash
f4fe62cd9e Merge remote-tracking branch 'origin/master' into lash/cache-faucet 2021-05-02 12:12:12 +02:00
nolash
cd2fc78d5b Add faucet filter with tests 2021-05-02 12:12:04 +02:00
17 changed files with 48 additions and 95 deletions

View File

@@ -16,6 +16,4 @@ def default_token(self):
return { return {
'symbol': self.default_token_symbol, 'symbol': self.default_token_symbol,
'address': self.default_token_address, 'address': self.default_token_address,
'name': self.default_token_name,
'decimals': self.default_token_decimals,
} }

View File

@@ -3,10 +3,7 @@ import logging
# external imports # external imports
import celery import celery
from cic_eth_registry.error import ( from cic_eth_registry.error import UnknownContractError
UnknownContractError,
NotAContractError,
)
from chainlib.status import Status as TxStatus from chainlib.status import Status as TxStatus
from chainlib.eth.address import to_checksum_address from chainlib.eth.address import to_checksum_address
from chainlib.eth.error import RequestMismatchException from chainlib.eth.error import RequestMismatchException
@@ -127,7 +124,8 @@ class CallbackFilter(SyncFilter):
(transfer_type, transfer_data) = parser(tx, conn) (transfer_type, transfer_data) = parser(tx, conn)
if transfer_type == None: if transfer_type == None:
continue continue
break else:
pass
except RequestMismatchException: except RequestMismatchException:
continue continue
@@ -170,9 +168,7 @@ class CallbackFilter(SyncFilter):
t = self.call_back(transfer_type, result) t = self.call_back(transfer_type, result)
logg.info('callback success task id {} tx {} queue {}'.format(t, tx.hash, t.queue)) logg.info('callback success task id {} tx {} queue {}'.format(t, tx.hash, t.queue))
except UnknownContractError: except UnknownContractError:
logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(self.queue, self.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))
except NotAContractError:
logg.debug('callback filter {}:{} skipping "transfer" on non-contract address {} tx {}'.format(self.queue, self.method, transfer_data['to'], tx.hash))
def __str__(self): def __str__(self):

View File

@@ -22,7 +22,6 @@ from chainlib.eth.connection import (
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainqueue.db.models.otx import Otx from chainqueue.db.models.otx import Otx
from cic_eth_registry.error import UnknownContractError from cic_eth_registry.error import UnknownContractError
from cic_eth_registry.erc20 import ERC20Token
import liveness.linux import liveness.linux
@@ -204,11 +203,6 @@ def main():
BaseTask.default_token_symbol = config.get('CIC_DEFAULT_TOKEN_SYMBOL') BaseTask.default_token_symbol = config.get('CIC_DEFAULT_TOKEN_SYMBOL')
BaseTask.default_token_address = registry.by_name(BaseTask.default_token_symbol) BaseTask.default_token_address = registry.by_name(BaseTask.default_token_symbol)
default_token = ERC20Token(chain_spec, rpc, BaseTask.default_token_address)
default_token.load(rpc)
BaseTask.default_token_decimals = default_token.decimals
BaseTask.default_token_name = default_token.name
BaseTask.run_dir = config.get('CIC_RUN_DIR') BaseTask.run_dir = config.get('CIC_RUN_DIR')
logg.info('default token set to {} {}'.format(BaseTask.default_token_symbol, BaseTask.default_token_address)) logg.info('default token set to {} {}'.format(BaseTask.default_token_symbol, BaseTask.default_token_address))

View File

@@ -12,10 +12,7 @@ import confini
import celery import celery
# local imports # local imports
from cic_eth.api import ( from cic_eth.api import Api
Api,
AdminApi,
)
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
@@ -56,19 +53,12 @@ celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=confi
queue = args.q queue = args.q
api = Api(config.get('CIC_CHAIN_SPEC'), queue=queue) api = Api(config.get('CIC_CHAIN_SPEC'), queue=queue)
admin_api = AdminApi(None)
def main(): def main():
t = admin_api.registry()
registry = t.get()
print('Registry address: {}'.format(registry))
t = api.default_token() t = api.default_token()
token_info = t.get() token_info = t.get()
print('Default token symbol: {}'.format(token_info['symbol'])) print('Default token symbol: {}'.format(token_info['symbol']))
print('Default token address: {}'.format(token_info['address'])) print('Default token address: {}'.format(token_info['address']))
logg.debug('Default token name: {}'.format(token_info['name']))
logg.debug('Default token decimals: {}'.format(token_info['decimals']))
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -33,8 +33,6 @@ class BaseTask(celery.Task):
create_gas_oracle = RPCGasOracle create_gas_oracle = RPCGasOracle
default_token_address = None default_token_address = None
default_token_symbol = None default_token_symbol = None
default_token_name = None
default_token_decimals = None
run_dir = '/run' run_dir = '/run'
def create_session(self): def create_session(self):

View File

@@ -1,4 +1,4 @@
cic-base~=0.1.2b11 cic-base==0.1.2b9
celery==4.4.7 celery==4.4.7
crypto-dev-signer~=0.4.14b3 crypto-dev-signer~=0.4.14b3
confini~=0.3.6rc3 confini~=0.3.6rc3
@@ -7,7 +7,7 @@ redis==3.5.3
alembic==1.4.2 alembic==1.4.2
websockets==8.1 websockets==8.1
requests~=2.24.0 requests~=2.24.0
eth_accounts_index~=0.0.11a12 eth_accounts_index~=0.0.11a11
erc20-transfer-authorization~=0.3.1a6 erc20-transfer-authorization~=0.3.1a6
uWSGI==2.0.19.1 uWSGI==2.0.19.1
semver==2.13.0 semver==2.13.0

View File

@@ -4,7 +4,7 @@ LOCALE_FALLBACK=en
LOCALE_PATH=/usr/src/cic-ussd/var/lib/locale/ LOCALE_PATH=/usr/src/cic-ussd/var/lib/locale/
MAX_BODY_LENGTH=1024 MAX_BODY_LENGTH=1024
PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I= PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I=
SERVICE_CODE=*483*46#,*483*061#,*384*96# SERVICE_CODE=*483*46#
[phone_number] [phone_number]
REGION=KE REGION=KE

View File

@@ -24,7 +24,7 @@ def from_wei(value: int) -> float:
"""This function converts values in Wei to a token in the cic network. """This function converts values in Wei to a token in the cic network.
:param value: Value in Wei :param value: Value in Wei
:type value: int :type value: int
:return: platform's default token equivalent of value in Wei :return: SRF equivalent of value in Wei
:rtype: float :rtype: float
""" """
value = float(value) / 1e+6 value = float(value) / 1e+6
@@ -33,9 +33,9 @@ def from_wei(value: int) -> float:
def to_wei(value: int) -> int: def to_wei(value: int) -> int:
"""This functions converts values from a token in the cic network to Wei. """This functions converts values from a token in the cic network to Wei.
:param value: Value in platform's default token :param value: Value in SRF
:type value: int :type value: int
:return: Wei equivalent of value in platform's default token :return: Wei equivalent of value in SRF
:rtype: int :rtype: int
""" """
return int(value * 1e+6) return int(value * 1e+6)

View File

@@ -13,7 +13,7 @@ import argparse
import logging import logging
import urllib import urllib
from xdg.BaseDirectory import xdg_config_home from xdg.BaseDirectory import xdg_config_home
from urllib import parse, request from urllib import request
# third-party imports # third-party imports
from confini import Config from confini import Config
@@ -92,9 +92,9 @@ def main():
data['text'] = user_input data['text'] = user_input
req = urllib.request.Request(url) req = urllib.request.Request(url)
urlencoded_data = parse.urlencode(data) data_str = json.dumps(data)
data_bytes = urlencoded_data.encode('utf-8') data_bytes = data_str.encode('utf-8')
req.add_header('Content-Type', 'application/x-www-form-urlencoded') req.add_header('Content-Type', 'application/json')
req.data = data_bytes req.data = data_bytes
response = urllib.request.urlopen(req) response = urllib.request.urlopen(req)
response_data = response.read().decode('utf-8') response_data = response.read().decode('utf-8')

View File

@@ -4,7 +4,6 @@
# standard imports # standard imports
import json import json
import logging import logging
from urllib.parse import parse_qs
# third-party imports # third-party imports
import celery import celery
@@ -34,7 +33,8 @@ from cic_ussd.requests import (get_request_endpoint,
from cic_ussd.runnable.server_base import exportable_parser, logg from cic_ussd.runnable.server_base import exportable_parser, logg
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
from cic_ussd.state_machine import UssdStateMachine from cic_ussd.state_machine import UssdStateMachine
from cic_ussd.validator import check_ip, check_request_content_length, validate_phone_number, validate_presence from cic_ussd.validator import check_ip, check_request_content_length, check_service_code, validate_phone_number, \
validate_presence
args = exportable_parser.parse_args() args = exportable_parser.parse_args()
@@ -124,9 +124,6 @@ else:
raise InitializationError(f'Default token data for: {chain_str} not found.') raise InitializationError(f'Default token data for: {chain_str} not found.')
valid_service_codes = config.get('APP_SERVICE_CODE').split(",")
def application(env, start_response): def application(env, start_response):
"""Loads python code for application to be accessible over web server """Loads python code for application to be accessible over web server
:param env: Object containing server and request information :param env: Object containing server and request information
@@ -142,27 +139,13 @@ def application(env, start_response):
if get_request_method(env=env) == 'POST' and get_request_endpoint(env=env) == '/': if get_request_method(env=env) == 'POST' and get_request_endpoint(env=env) == '/':
if env.get('CONTENT_TYPE') != 'application/x-www-form-urlencoded': # get post data
start_response('405 Play by the rules', errors_headers) post_data = json.load(env.get('wsgi.input'))
return []
post_data = env.get('wsgi.input').read() service_code = post_data.get('serviceCode')
post_data = post_data.decode('utf-8') phone_number = post_data.get('phoneNumber')
external_session_id = post_data.get('sessionId')
try: user_input = post_data.get('text')
post_data = parse_qs(post_data)
except TypeError:
start_response('400 Size matters', errors_headers)
return []
service_code = post_data.get('serviceCode')[0]
phone_number = post_data.get('phoneNumber')[0]
external_session_id = post_data.get('sessionId')[0]
try:
user_input = post_data.get('text')[0]
except TypeError:
user_input = ""
# add validation for phone number # add validation for phone number
if phone_number: if phone_number:
@@ -179,14 +162,14 @@ def application(env, start_response):
return [] return []
# validate service code # validate service code
if service_code not in valid_service_codes: if not check_service_code(code=service_code, config=config):
response = define_multilingual_responses( response = define_multilingual_responses(
key='ussd.kenya.invalid_service_code', key='ussd.kenya.invalid_service_code',
locales=['en', 'sw'], locales=['en', 'sw'],
prefix='END', prefix='END',
valid_service_code=valid_service_codes[0]) valid_service_code=config.get('APP_SERVICE_CODE'))
response_bytes, headers = define_response_with_content(headers=headers, response=response) response_bytes, headers = define_response_with_content(headers=errors_headers, response=response)
start_response('200 OK', headers) start_response('400 Invalid service code', headers)
return [response_bytes] return [response_bytes]
# validate phone number # validate phone number
@@ -209,8 +192,3 @@ def application(env, start_response):
start_response('200 OK,', headers) start_response('200 OK,', headers)
SessionBase.session.close() SessionBase.session.close()
return [response_bytes] return [response_bytes]
else:
start_response('405 Play by the rules', errors_headers)
return []

View File

@@ -12,7 +12,6 @@ from cic_ussd.chain import Chain
from cic_ussd.db.models.account import AccountStatus, Account from cic_ussd.db.models.account import AccountStatus, Account
from cic_ussd.operations import save_to_in_memory_ussd_session_data from cic_ussd.operations import save_to_in_memory_ussd_session_data
from cic_ussd.phone_number import get_user_by_phone_number from cic_ussd.phone_number import get_user_by_phone_number
from cic_ussd.processor import retrieve_token_symbol
from cic_ussd.redis import create_cached_data_key, get_cached_data from cic_ussd.redis import create_cached_data_key, get_cached_data
from cic_ussd.transactions import OutgoingTransactionProcessor from cic_ussd.transactions import OutgoingTransactionProcessor
@@ -125,18 +124,14 @@ def process_transaction_request(state_machine_data: Tuple[str, dict, Account]):
""" """
user_input, ussd_session, user = state_machine_data user_input, ussd_session, user = state_machine_data
# retrieve token symbol
chain_str = Chain.spec.__str__()
# get user from phone number # get user from phone number
recipient_phone_number = ussd_session.get('session_data').get('recipient_phone_number') recipient_phone_number = ussd_session.get('session_data').get('recipient_phone_number')
recipient = get_user_by_phone_number(phone_number=recipient_phone_number) recipient = get_user_by_phone_number(phone_number=recipient_phone_number)
to_address = recipient.blockchain_address to_address = recipient.blockchain_address
from_address = user.blockchain_address from_address = user.blockchain_address
amount = int(ussd_session.get('session_data').get('transaction_amount')) amount = int(ussd_session.get('session_data').get('transaction_amount'))
token_symbol = retrieve_token_symbol(chain_str=chain_str) chain_str = Chain.spec.__str__()
outgoing_tx_processor = OutgoingTransactionProcessor(chain_str=chain_str, outgoing_tx_processor = OutgoingTransactionProcessor(chain_str=chain_str,
from_address=from_address, from_address=from_address,
to_address=to_address) to_address=to_address)
outgoing_tx_processor.process_outgoing_transfer_transaction(amount=amount, token_symbol=token_symbol) outgoing_tx_processor.process_outgoing_transfer_transaction(amount=amount)

View File

@@ -120,7 +120,7 @@ class OutgoingTransactionProcessor:
self.from_address = from_address self.from_address = from_address
self.to_address = to_address self.to_address = to_address
def process_outgoing_transfer_transaction(self, amount: int, token_symbol: str): def process_outgoing_transfer_transaction(self, amount: int, token_symbol='SRF'):
"""This function initiates standard transfers between one account to another """This function initiates standard transfers between one account to another
:param amount: The amount of tokens to be sent :param amount: The amount of tokens to be sent
:type amount: int :type amount: int

View File

@@ -45,6 +45,19 @@ def check_request_content_length(config: Config, env: dict):
config.get('APP_MAX_BODY_LENGTH')) config.get('APP_MAX_BODY_LENGTH'))
def check_service_code(code: str, config: Config):
"""Checks whether provided code matches expected service code
:param config: A dictionary object containing configuration values
:type config: Config
:param code: Service code passed over request
:type code: str
:return: Service code validity
:rtype: boolean
"""
return code == config.get('APP_SERVICE_CODE')
def check_known_user(phone: str): def check_known_user(phone: str):
""" """
This method attempts to ascertain whether the user already exists and is known to the system. This method attempts to ascertain whether the user already exists and is known to the system.

View File

@@ -158,8 +158,6 @@ en:
Your Sarafu-Network balances is: %{token_balance} Your Sarafu-Network balances is: %{token_balance}
00. Back 00. Back
99. Exit 99. Exit
invalid_service_code: |-
Please dial %{valid_service_code} to access Sarafu Network
help: |- help: |-
CON For assistance call %{support_phone} CON For assistance call %{support_phone}
00. Back 00. Back

View File

@@ -158,8 +158,6 @@ sw:
Akaunti yako ya Sarafu-Network ina salio ifuatayo: %{token_balance} Akaunti yako ya Sarafu-Network ina salio ifuatayo: %{token_balance}
00. Nyuma 00. Nyuma
99. Ondoka 99. Ondoka
invalid_service_code: |-
Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu
help: |- help: |-
CON Kwa usaidizi piga simu %{support_phone} CON Kwa usaidizi piga simu %{support_phone}
0. Nyuma 0. Nyuma

View File

@@ -54,10 +54,10 @@ ENV PATH $NVM_DIR/versions/node//v$NODE_VERSION/bin:$PATH
ARG pip_extra_args="" ARG pip_extra_args=""
ARG pip_index_url=https://pypi.org/simple ARG pip_index_url=https://pypi.org/simple
ARG pip_extra_index_url=https://pip.grassrootseconomics.net:8433 ARG pip_extra_index_url=https://pip.grassrootseconomics.net:8433
ARG cic_base_version=0.1.2b11 ARG cic_base_version=0.1.2b8
ARG cic_eth_version=0.11.0b14 ARG cic_eth_version=0.11.0b12
ARG sarafu_token_version=0.0.1a8 ARG sarafu_token_version=0.0.1a8
ARG sarafu_faucet_version=0.0.3a3 ARG sarafu_faucet_version=0.0.3a2
RUN pip install --index-url https://pypi.org/simple --extra-index-url $pip_extra_index_url \ RUN pip install --index-url https://pypi.org/simple --extra-index-url $pip_extra_index_url \
cic-base[full_graph]==$cic_base_version \ cic-base[full_graph]==$cic_base_version \
cic-eth==$cic_eth_version \ cic-eth==$cic_eth_version \

View File

@@ -33,7 +33,6 @@ from chainlib.eth.tx import TxFactory
from chainlib.jsonrpc import jsonrpc_template from chainlib.jsonrpc import jsonrpc_template
from chainlib.eth.error import EthException from chainlib.eth.error import EthException
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.constant import ZERO_ADDRESS
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore.dict import DictKeystore from crypto_dev_signer.keystore.dict import DictKeystore
from cic_types.models.person import Person from cic_types.models.person import Person
@@ -52,7 +51,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('--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('-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('-r', '--registry-address', type=str, dest='r', help='CIC Registry address')
argparser.add_argument('--token-symbol', default='GFT', type=str, dest='token_symbol', help='Token symbol to use for trnsactions') argparser.add_argument('--token-symbol', default='SRF', 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('--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('--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') argparser.add_argument('-q', type=str, default='cic-eth', help='celery queue to submit transaction tasks to')
@@ -253,10 +252,6 @@ def main():
except ValueError as e: except ValueError as e:
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e)) logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
sys.exit(1) 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(sarafu_token_address))
syncer_backend = MemBackend(chain_str, 0) syncer_backend = MemBackend(chain_str, 0)