Merge remote-tracking branch 'origin/master' into lash/import-ussd
This commit is contained in:
commit
64e4b10b3a
@ -27,7 +27,7 @@ def define_account_tx_metadata(user: User):
|
|||||||
if account_metadata:
|
if account_metadata:
|
||||||
account_metadata = json.loads(account_metadata)
|
account_metadata = json.loads(account_metadata)
|
||||||
person = Person()
|
person = Person()
|
||||||
deserialized_person = person.deserialize(metadata=account_metadata)
|
deserialized_person = person.deserialize(person_data=account_metadata)
|
||||||
given_name = deserialized_person.given_name
|
given_name = deserialized_person.given_name
|
||||||
family_name = deserialized_person.family_name
|
family_name = deserialized_person.family_name
|
||||||
phone_number = deserialized_person.tel
|
phone_number = deserialized_person.tel
|
||||||
@ -46,4 +46,4 @@ def retrieve_account_statement(blockchain_address: str):
|
|||||||
callback_task='cic_ussd.tasks.callback_handler.process_statement_callback',
|
callback_task='cic_ussd.tasks.callback_handler.process_statement_callback',
|
||||||
callback_param=blockchain_address
|
callback_param=blockchain_address
|
||||||
)
|
)
|
||||||
result = cic_eth_api.list(address=blockchain_address, limit=9)
|
cic_eth_api.list(address=blockchain_address, limit=9)
|
||||||
|
@ -128,8 +128,8 @@
|
|||||||
},
|
},
|
||||||
"22": {
|
"22": {
|
||||||
"description": "Pin entry menu.",
|
"description": "Pin entry menu.",
|
||||||
"display_key": "ussd.kenya.standard_pin_authorization",
|
"display_key": "ussd.kenya.display_metadata_pin_authorization",
|
||||||
"name": "standard_pin_authorization",
|
"name": "display_metadata_pin_authorization",
|
||||||
"parent": "start"
|
"parent": "start"
|
||||||
},
|
},
|
||||||
"23": {
|
"23": {
|
||||||
@ -230,9 +230,22 @@
|
|||||||
},
|
},
|
||||||
"39": {
|
"39": {
|
||||||
"description": "Menu to instruct users to call the office.",
|
"description": "Menu to instruct users to call the office.",
|
||||||
"display_key": "ussd.key.help",
|
"display_key": "ussd.kenya.help",
|
||||||
"name": "help",
|
"name": "help",
|
||||||
"parent": null
|
"parent": null
|
||||||
|
},
|
||||||
|
"40": {
|
||||||
|
"description": "Menu to display a user's entire profile",
|
||||||
|
"display_key": "ussd.kenya.display_user_metadata",
|
||||||
|
"name": "display_user_metadata",
|
||||||
|
"parent": "account_management"
|
||||||
|
},
|
||||||
|
"41": {
|
||||||
|
"description": "The recipient is not in the system",
|
||||||
|
"display_key": "ussd.kenya.exit_invalid_recipient",
|
||||||
|
"name": "exit_invalid_recipient",
|
||||||
|
"parent": null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -92,7 +92,7 @@ class UserMetadata:
|
|||||||
|
|
||||||
# validate data
|
# validate data
|
||||||
person = Person()
|
person = Person()
|
||||||
deserialized_person = person.deserialize(metadata=json.loads(data))
|
deserialized_person = person.deserialize(person_data=json.loads(data))
|
||||||
|
|
||||||
cache_data(key=self.metadata_pointer, data=json.dumps(deserialized_person.serialize()))
|
cache_data(key=self.metadata_pointer, data=json.dumps(deserialized_person.serialize()))
|
||||||
elif status == 404:
|
elif status == 404:
|
||||||
|
@ -15,6 +15,7 @@ from cic_ussd.balance import BalanceManager, compute_operational_balance, get_ca
|
|||||||
from cic_ussd.chain import Chain
|
from cic_ussd.chain import Chain
|
||||||
from cic_ussd.db.models.user import AccountStatus, User
|
from cic_ussd.db.models.user import AccountStatus, User
|
||||||
from cic_ussd.db.models.ussd_session import UssdSession
|
from cic_ussd.db.models.ussd_session import UssdSession
|
||||||
|
from cic_ussd.error import UserMetadataNotFoundError
|
||||||
from cic_ussd.menu.ussd_menu import UssdMenu
|
from cic_ussd.menu.ussd_menu import UssdMenu
|
||||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||||
from cic_ussd.phone_number import get_user_by_phone_number
|
from cic_ussd.phone_number import get_user_by_phone_number
|
||||||
@ -22,6 +23,7 @@ from cic_ussd.redis import cache_data, create_cached_data_key, get_cached_data
|
|||||||
from cic_ussd.state_machine import UssdStateMachine
|
from cic_ussd.state_machine import UssdStateMachine
|
||||||
from cic_ussd.conversions import to_wei, from_wei
|
from cic_ussd.conversions import to_wei, from_wei
|
||||||
from cic_ussd.translation import translation_for
|
from cic_ussd.translation import translation_for
|
||||||
|
from cic_types.models.person import generate_metadata_pointer, get_contact_data_from_vcard
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -136,7 +138,7 @@ def process_transaction_pin_authorization(user: User, display_key: str, ussd_ses
|
|||||||
tx_sender_information = define_account_tx_metadata(user=user)
|
tx_sender_information = define_account_tx_metadata(user=user)
|
||||||
|
|
||||||
token_symbol = 'SRF'
|
token_symbol = 'SRF'
|
||||||
user_input = ussd_session.get('user_input').split('*')[-1]
|
user_input = ussd_session.get('session_data').get('transaction_amount')
|
||||||
transaction_amount = to_wei(value=int(user_input))
|
transaction_amount = to_wei(value=int(user_input))
|
||||||
logg.debug('Requires integration to determine user tokens.')
|
logg.debug('Requires integration to determine user tokens.')
|
||||||
return process_pin_authorization(
|
return process_pin_authorization(
|
||||||
@ -187,21 +189,55 @@ def format_transactions(transactions: list, preferred_language: str):
|
|||||||
value = transaction.get('to_value')
|
value = transaction.get('to_value')
|
||||||
timestamp = transaction.get('timestamp')
|
timestamp = transaction.get('timestamp')
|
||||||
action_tag = transaction.get('action_tag')
|
action_tag = transaction.get('action_tag')
|
||||||
|
direction = transaction.get('direction')
|
||||||
token_symbol = 'SRF'
|
token_symbol = 'SRF'
|
||||||
|
|
||||||
if action_tag == 'SENT' or action_tag == 'ULITUMA':
|
if action_tag == 'SENT' or action_tag == 'ULITUMA':
|
||||||
formatted_transactions += f'{action_tag} {value} {token_symbol} {recipient_phone_number} {timestamp}.\n'
|
formatted_transactions += f'{action_tag} {value} {token_symbol} {direction} {recipient_phone_number} {timestamp}.\n'
|
||||||
else:
|
else:
|
||||||
formatted_transactions += f'{action_tag} {value} {token_symbol} {sender_phone_number} {timestamp}. \n'
|
formatted_transactions += f'{action_tag} {value} {token_symbol} {direction} {sender_phone_number} {timestamp}. \n'
|
||||||
return formatted_transactions
|
return formatted_transactions
|
||||||
else:
|
else:
|
||||||
if preferred_language == 'en':
|
if preferred_language == 'en':
|
||||||
formatted_transactions = 'Empty'
|
formatted_transactions = 'NO TRANSACTION HISTORY'
|
||||||
else:
|
else:
|
||||||
formatted_transactions = 'Hamna historia'
|
formatted_transactions = 'HAMNA RIPOTI YA MATUMIZI'
|
||||||
return formatted_transactions
|
return formatted_transactions
|
||||||
|
|
||||||
|
|
||||||
|
def process_display_user_metadata(user: User, display_key: str):
|
||||||
|
"""
|
||||||
|
:param user:
|
||||||
|
:type user:
|
||||||
|
:param display_key:
|
||||||
|
:type display_key:
|
||||||
|
"""
|
||||||
|
key = generate_metadata_pointer(
|
||||||
|
identifier=blockchain_address_to_metadata_pointer(blockchain_address=user.blockchain_address),
|
||||||
|
cic_type='cic.person'
|
||||||
|
)
|
||||||
|
user_metadata = get_cached_data(key)
|
||||||
|
if user_metadata:
|
||||||
|
user_metadata = json.loads(user_metadata)
|
||||||
|
contact_data = get_contact_data_from_vcard(vcard=user_metadata.get('vcard'))
|
||||||
|
logg.debug(f'{contact_data}')
|
||||||
|
full_name = f'{contact_data.get("given")} {contact_data.get("family")}'
|
||||||
|
gender = user_metadata.get('gender')
|
||||||
|
products = ', '.join(user_metadata.get('products'))
|
||||||
|
location = user_metadata.get('location').get('area_name')
|
||||||
|
|
||||||
|
return translation_for(
|
||||||
|
key=display_key,
|
||||||
|
preferred_language=user.preferred_language,
|
||||||
|
full_name=full_name,
|
||||||
|
gender=gender,
|
||||||
|
location=location,
|
||||||
|
products=products
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise UserMetadataNotFoundError(f'Expected user metadata but found none in cache for key: {user.blockchain_address}')
|
||||||
|
|
||||||
|
|
||||||
def process_account_statement(user: User, display_key: str, ussd_session: dict):
|
def process_account_statement(user: User, display_key: str, ussd_session: dict):
|
||||||
"""
|
"""
|
||||||
:param user:
|
:param user:
|
||||||
@ -229,7 +265,7 @@ def process_account_statement(user: User, display_key: str, ussd_session: dict):
|
|||||||
middle_transaction_set += transactions[3:][:3]
|
middle_transaction_set += transactions[3:][:3]
|
||||||
first_transaction_set += transactions[:3]
|
first_transaction_set += transactions[:3]
|
||||||
# there are probably much cleaner and operational inexpensive ways to do this so find them
|
# there are probably much cleaner and operational inexpensive ways to do this so find them
|
||||||
elif 4 < len(transactions) < 7:
|
elif 3 < len(transactions) < 7:
|
||||||
middle_transaction_set += transactions[3:]
|
middle_transaction_set += transactions[3:]
|
||||||
first_transaction_set += transactions[:3]
|
first_transaction_set += transactions[:3]
|
||||||
else:
|
else:
|
||||||
@ -349,18 +385,27 @@ def process_request(user_input: str, user: User, ussd_session: Optional[dict] =
|
|||||||
if user.has_valid_pin():
|
if user.has_valid_pin():
|
||||||
last_ussd_session = retrieve_most_recent_ussd_session(phone_number=user.phone_number)
|
last_ussd_session = retrieve_most_recent_ussd_session(phone_number=user.phone_number)
|
||||||
|
|
||||||
key = create_cached_data_key(
|
key = generate_metadata_pointer(
|
||||||
identifier=blockchain_address_to_metadata_pointer(blockchain_address=user.blockchain_address),
|
identifier=blockchain_address_to_metadata_pointer(blockchain_address=user.blockchain_address),
|
||||||
salt='cic.person'
|
cic_type='cic.person'
|
||||||
)
|
)
|
||||||
|
logg.debug(f'METADATA POINTER: {key}')
|
||||||
user_metadata = get_cached_data(key=key)
|
user_metadata = get_cached_data(key=key)
|
||||||
|
logg.debug(f'METADATA: {user_metadata}')
|
||||||
|
|
||||||
if last_ussd_session:
|
if last_ussd_session:
|
||||||
# get last state
|
# get last state
|
||||||
last_state = last_ussd_session.state
|
last_state = last_ussd_session.state
|
||||||
logg.debug(f'LAST USSD SESSION STATE: {last_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 is account_creation_prompt and metadata exists, show start menu
|
||||||
if last_state == 'account_creation_prompt' and user_metadata is not None:
|
if last_state in [
|
||||||
|
'account_creation_prompt',
|
||||||
|
'exit',
|
||||||
|
'exit_invalid_pin',
|
||||||
|
'exit_invalid_new_pin',
|
||||||
|
'exit_pin_mismatch',
|
||||||
|
'exit_invalid_request'
|
||||||
|
] and user_metadata is not None:
|
||||||
return UssdMenu.find_by_name(name='start')
|
return UssdMenu.find_by_name(name='start')
|
||||||
else:
|
else:
|
||||||
return UssdMenu.find_by_name(name=last_state)
|
return UssdMenu.find_by_name(name=last_state)
|
||||||
@ -420,9 +465,13 @@ def custom_display_text(
|
|||||||
return process_start_menu(display_key=display_key, user=user)
|
return process_start_menu(display_key=display_key, user=user)
|
||||||
elif 'pin_authorization' in menu_name:
|
elif 'pin_authorization' in menu_name:
|
||||||
return process_pin_authorization(display_key=display_key, user=user)
|
return process_pin_authorization(display_key=display_key, user=user)
|
||||||
|
elif 'enter_current_pin' in menu_name:
|
||||||
|
return process_pin_authorization(display_key=display_key, user=user)
|
||||||
elif menu_name == 'account_balances':
|
elif menu_name == 'account_balances':
|
||||||
return process_account_balances(display_key=display_key, user=user, ussd_session=ussd_session)
|
return process_account_balances(display_key=display_key, user=user, ussd_session=ussd_session)
|
||||||
elif 'transaction_set' in menu_name:
|
elif 'transaction_set' in menu_name:
|
||||||
return process_account_statement(display_key=display_key, user=user, ussd_session=ussd_session)
|
return process_account_statement(display_key=display_key, user=user, ussd_session=ussd_session)
|
||||||
|
elif menu_name == 'display_user_metadata':
|
||||||
|
return process_display_user_metadata(display_key=display_key, user=user)
|
||||||
else:
|
else:
|
||||||
return translation_for(key=display_key, preferred_language=user.preferred_language)
|
return translation_for(key=display_key, preferred_language=user.preferred_language)
|
||||||
|
@ -35,7 +35,8 @@ from cic_ussd.requests import (get_request_endpoint,
|
|||||||
process_pin_reset_requests)
|
process_pin_reset_requests)
|
||||||
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, check_service_code, validate_phone_number
|
from cic_ussd.validator import check_ip, check_request_content_length, check_service_code, validate_phone_number, \
|
||||||
|
validate_presence
|
||||||
|
|
||||||
logging.basicConfig(level=logging.WARNING)
|
logging.basicConfig(level=logging.WARNING)
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
@ -101,9 +102,15 @@ InMemoryUssdSession.redis_cache = InMemoryStore.cache
|
|||||||
UserMetadata.base_url = config.get('CIC_META_URL')
|
UserMetadata.base_url = config.get('CIC_META_URL')
|
||||||
|
|
||||||
# define signer values
|
# define signer values
|
||||||
Signer.gpg_path = config.get('PGP_EXPORT_DIR')
|
export_dir = config.get('PGP_EXPORT_DIR')
|
||||||
|
if export_dir:
|
||||||
|
validate_presence(path=export_dir)
|
||||||
|
Signer.gpg_path = export_dir
|
||||||
Signer.gpg_passphrase = config.get('PGP_PASSPHRASE')
|
Signer.gpg_passphrase = config.get('PGP_PASSPHRASE')
|
||||||
Signer.key_file_path = f"{config.get('PGP_KEYS_PATH')}{config.get('PGP_PRIVATE_KEYS')}"
|
key_file_path = f"{config.get('PGP_KEYS_PATH')}{config.get('PGP_PRIVATE_KEYS')}"
|
||||||
|
if key_file_path:
|
||||||
|
validate_presence(path=key_file_path)
|
||||||
|
Signer.key_file_path = key_file_path
|
||||||
|
|
||||||
# initialize celery app
|
# initialize celery app
|
||||||
celery.Celery(backend=config.get('CELERY_RESULT_URL'), broker=config.get('CELERY_BROKER_URL'))
|
celery.Celery(backend=config.get('CELERY_RESULT_URL'), broker=config.get('CELERY_BROKER_URL'))
|
||||||
|
@ -16,6 +16,7 @@ from cic_ussd.metadata.signer import Signer
|
|||||||
from cic_ussd.metadata.user import UserMetadata
|
from cic_ussd.metadata.user import UserMetadata
|
||||||
from cic_ussd.redis import InMemoryStore
|
from cic_ussd.redis import InMemoryStore
|
||||||
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
|
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
|
||||||
|
from cic_ussd.validator import validate_presence
|
||||||
|
|
||||||
logging.basicConfig(level=logging.WARNING)
|
logging.basicConfig(level=logging.WARNING)
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
@ -65,9 +66,15 @@ InMemoryUssdSession.redis_cache = InMemoryStore.cache
|
|||||||
UserMetadata.base_url = config.get('CIC_META_URL')
|
UserMetadata.base_url = config.get('CIC_META_URL')
|
||||||
|
|
||||||
# define signer values
|
# define signer values
|
||||||
Signer.gpg_path = config.get('PGP_EXPORT_DIR')
|
export_dir = config.get('PGP_EXPORT_DIR')
|
||||||
|
if export_dir:
|
||||||
|
validate_presence(path=export_dir)
|
||||||
|
Signer.gpg_path = export_dir
|
||||||
Signer.gpg_passphrase = config.get('PGP_PASSPHRASE')
|
Signer.gpg_passphrase = config.get('PGP_PASSPHRASE')
|
||||||
Signer.key_file_path = f"{config.get('PGP_KEYS_PATH')}{config.get('PGP_PRIVATE_KEYS')}"
|
key_file_path = f"{config.get('PGP_KEYS_PATH')}{config.get('PGP_PRIVATE_KEYS')}"
|
||||||
|
if key_file_path:
|
||||||
|
validate_presence(path=key_file_path)
|
||||||
|
Signer.key_file_path = key_file_path
|
||||||
|
|
||||||
# set up celery
|
# set up celery
|
||||||
current_app = celery.Celery(__name__)
|
current_app = celery.Celery(__name__)
|
||||||
|
@ -78,9 +78,10 @@ def save_recipient_phone_to_session_data(state_machine_data: Tuple[str, dict, Us
|
|||||||
:type state_machine_data: str
|
:type state_machine_data: str
|
||||||
"""
|
"""
|
||||||
user_input, ussd_session, user = state_machine_data
|
user_input, ussd_session, user = state_machine_data
|
||||||
session_data = {
|
|
||||||
'recipient_phone_number': user_input
|
session_data = ussd_session.get('session_data') or {}
|
||||||
}
|
session_data['recipient_phone_number'] = user_input
|
||||||
|
|
||||||
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
||||||
|
|
||||||
|
|
||||||
@ -109,9 +110,10 @@ def save_transaction_amount_to_session_data(state_machine_data: Tuple[str, dict,
|
|||||||
:type state_machine_data: str
|
:type state_machine_data: str
|
||||||
"""
|
"""
|
||||||
user_input, ussd_session, user = state_machine_data
|
user_input, ussd_session, user = state_machine_data
|
||||||
session_data = {
|
|
||||||
'transaction_amount': user_input
|
session_data = ussd_session.get('session_data') or {}
|
||||||
}
|
session_data['transaction_amount'] = user_input
|
||||||
|
|
||||||
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, User]):
|
|||||||
# validate user metadata
|
# validate user metadata
|
||||||
person = Person()
|
person = Person()
|
||||||
user_metadata = json.loads(user_metadata)
|
user_metadata = json.loads(user_metadata)
|
||||||
deserialized_person = person.deserialize(metadata=user_metadata)
|
deserialized_person = person.deserialize(person_data=user_metadata)
|
||||||
|
|
||||||
# edit specific metadata attribute
|
# edit specific metadata attribute
|
||||||
if given_name:
|
if given_name:
|
||||||
|
@ -143,14 +143,18 @@ def define_transaction_action_tag(
|
|||||||
# check preferred language
|
# check preferred language
|
||||||
if preferred_language == 'en':
|
if preferred_language == 'en':
|
||||||
action_tag = 'SENT'
|
action_tag = 'SENT'
|
||||||
|
direction = 'TO'
|
||||||
else:
|
else:
|
||||||
action_tag = 'ULITUMA'
|
action_tag = 'ULITUMA'
|
||||||
|
direction = 'KWA'
|
||||||
else:
|
else:
|
||||||
if preferred_language == 'en':
|
if preferred_language == 'en':
|
||||||
action_tag = 'RECEIVED'
|
action_tag = 'RECEIVED'
|
||||||
|
direction = 'FROM'
|
||||||
else:
|
else:
|
||||||
action_tag = 'ULIPOKEA'
|
action_tag = 'ULIPOKEA'
|
||||||
return action_tag
|
direction = 'KUTOKA'
|
||||||
|
return action_tag, direction
|
||||||
|
|
||||||
|
|
||||||
@celery_app.task
|
@celery_app.task
|
||||||
@ -175,15 +179,17 @@ def process_statement_callback(result, param: str, status_code: int):
|
|||||||
|
|
||||||
# check if sender is in the system
|
# check if sender is in the system
|
||||||
sender: User = session.query(User).filter_by(blockchain_address=sender_blockchain_address).first()
|
sender: User = session.query(User).filter_by(blockchain_address=sender_blockchain_address).first()
|
||||||
|
owner: User = session.query(User).filter_by(blockchain_address=param).first()
|
||||||
if sender:
|
if sender:
|
||||||
processed_transaction['sender_phone_number'] = sender.phone_number
|
processed_transaction['sender_phone_number'] = sender.phone_number
|
||||||
|
|
||||||
action_tag = define_transaction_action_tag(
|
action_tag, direction = define_transaction_action_tag(
|
||||||
preferred_language=sender.preferred_language,
|
preferred_language=owner.preferred_language,
|
||||||
sender_blockchain_address=sender_blockchain_address,
|
sender_blockchain_address=sender_blockchain_address,
|
||||||
param=param
|
param=param
|
||||||
)
|
)
|
||||||
processed_transaction['action_tag'] = action_tag
|
processed_transaction['action_tag'] = action_tag
|
||||||
|
processed_transaction['direction'] = direction
|
||||||
|
|
||||||
else:
|
else:
|
||||||
processed_transaction['sender_phone_number'] = 'GRASSROOTS ECONOMICS'
|
processed_transaction['sender_phone_number'] = 'GRASSROOTS ECONOMICS'
|
||||||
@ -197,8 +203,8 @@ def process_statement_callback(result, param: str, status_code: int):
|
|||||||
logg.warning(f'Tx with recipient not found in cic-ussd')
|
logg.warning(f'Tx with recipient not found in cic-ussd')
|
||||||
|
|
||||||
# add transaction values
|
# add transaction values
|
||||||
processed_transaction['to_value'] = from_wei(value=transaction.get('to_value'))
|
processed_transaction['to_value'] = from_wei(value=transaction.get('to_value')).__str__()
|
||||||
processed_transaction['from_value'] = from_wei(value=transaction.get('from_value'))
|
processed_transaction['from_value'] = from_wei(value=transaction.get('from_value')).__str__()
|
||||||
|
|
||||||
raw_timestamp = transaction.get('timestamp')
|
raw_timestamp = transaction.get('timestamp')
|
||||||
timestamp = datetime.utcfromtimestamp(raw_timestamp).strftime('%d/%m/%y, %H:%M')
|
timestamp = datetime.utcfromtimestamp(raw_timestamp).strftime('%d/%m/%y, %H:%M')
|
||||||
|
@ -47,7 +47,7 @@ def to_wei(value: int) -> int:
|
|||||||
:return: Wei equivalent of value in SRF
|
:return: Wei equivalent of value in SRF
|
||||||
:rtype: int
|
:rtype: int
|
||||||
"""
|
"""
|
||||||
return int(value * 1e+18)
|
return int(value * 1e+6)
|
||||||
|
|
||||||
|
|
||||||
class IncomingTransactionProcessor:
|
class IncomingTransactionProcessor:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# standard imports
|
# standard imports
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
@ -118,7 +119,7 @@ def validate_phone_number(phone: str):
|
|||||||
|
|
||||||
|
|
||||||
def validate_response_type(processor_response: str) -> bool:
|
def validate_response_type(processor_response: str) -> bool:
|
||||||
"""1*3443*3443*Philip*Wanga*1*Juja*Software Developer*2*3
|
"""
|
||||||
This function checks the prefix for a corresponding menu's text from the response offered by the Ussd Processor and
|
This function checks the prefix for a corresponding menu's text from the response offered by the Ussd Processor and
|
||||||
determines whether the response should prompt the end of a ussd session or the
|
determines whether the response should prompt the end of a ussd session or the
|
||||||
:param processor_response: A ussd menu's text value.
|
:param processor_response: A ussd menu's text value.
|
||||||
@ -134,3 +135,14 @@ def validate_response_type(processor_response: str) -> bool:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def validate_presence(path: str):
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
is_present = os.path.exists(path=path)
|
||||||
|
|
||||||
|
if not is_present:
|
||||||
|
raise ValueError(f'Directory/File in path: {path} not found.')
|
||||||
|
else:
|
||||||
|
logg.debug(f'Loading data from: {path}')
|
||||||
|
@ -4,5 +4,6 @@
|
|||||||
"enter_gender",
|
"enter_gender",
|
||||||
"enter_age",
|
"enter_age",
|
||||||
"enter_location",
|
"enter_location",
|
||||||
"enter_products"
|
"enter_products",
|
||||||
|
"display_metadata_pin_authorization"
|
||||||
]
|
]
|
@ -82,7 +82,7 @@ def test_format_user_metadata(create_activated_user,
|
|||||||
from cic_types.models.person import Person
|
from cic_types.models.person import Person
|
||||||
formatted_user_metadata = format_user_metadata(metadata=complete_user_metadata, user=create_activated_user)
|
formatted_user_metadata = format_user_metadata(metadata=complete_user_metadata, user=create_activated_user)
|
||||||
person = Person()
|
person = Person()
|
||||||
user_metadata = person.deserialize(metadata=formatted_user_metadata)
|
user_metadata = person.deserialize(person_data=formatted_user_metadata)
|
||||||
assert formatted_user_metadata == user_metadata.serialize()
|
assert formatted_user_metadata == user_metadata.serialize()
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
{
|
{
|
||||||
"trigger": "scan_data",
|
"trigger": "scan_data",
|
||||||
"source": "exit_invalid_recipient",
|
"source": "exit_invalid_recipient",
|
||||||
"dest": "send_enter_recipient",
|
"dest": "enter_transaction_recipient",
|
||||||
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
|
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -49,13 +49,13 @@
|
|||||||
"after": "cic_ussd.state_machine.logic.sms.upsell_unregistered_recipient"
|
"after": "cic_ussd.state_machine.logic.sms.upsell_unregistered_recipient"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"trigger": "feed_char",
|
"trigger": "scan_data",
|
||||||
"source": "exit_successful_transaction",
|
"source": "exit_successful_transaction",
|
||||||
"dest": "start",
|
"dest": "start",
|
||||||
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
|
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"trigger": "feed_char",
|
"trigger": "scan_data",
|
||||||
"source": "exit_successful_transaction",
|
"source": "exit_successful_transaction",
|
||||||
"dest": "exit",
|
"dest": "exit",
|
||||||
"conditions": "cic_ussd.state_machine.logic.menu.menu_ninety_nine_selected"
|
"conditions": "cic_ussd.state_machine.logic.menu.menu_ninety_nine_selected"
|
||||||
|
@ -26,18 +26,18 @@
|
|||||||
{
|
{
|
||||||
"trigger": "scan_data",
|
"trigger": "scan_data",
|
||||||
"source": "metadata_management",
|
"source": "metadata_management",
|
||||||
"dest": "standard_pin_authorization",
|
"dest": "display_metadata_pin_authorization",
|
||||||
"conditions": "cic_ussd.state_machine.logic.menu.menu_five_selected"
|
"conditions": "cic_ussd.state_machine.logic.menu.menu_five_selected"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"trigger": "scan_data",
|
"trigger": "scan_data",
|
||||||
"source": "standard_pin_authorization",
|
"source": "display_metadata_pin_authorization",
|
||||||
"dest": "display_user_metadata",
|
"dest": "display_user_metadata",
|
||||||
"conditions": "cic_ussd.state_machine.logic.pin.is_authorized_pin"
|
"conditions": "cic_ussd.state_machine.logic.pin.is_authorized_pin"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"trigger": "scan_data",
|
"trigger": "scan_data",
|
||||||
"source": "standard_pin_authorization",
|
"source": "display_metadata_pin_authorization",
|
||||||
"dest": "exit_pin_blocked",
|
"dest": "exit_pin_blocked",
|
||||||
"conditions": "cic_ussd.state_machine.logic.pin.is_locked_account"
|
"conditions": "cic_ussd.state_machine.logic.pin.is_locked_account"
|
||||||
},
|
},
|
||||||
|
@ -55,8 +55,8 @@ en:
|
|||||||
4. Edit products
|
4. Edit products
|
||||||
5. View my profile
|
5. View my profile
|
||||||
0. Back
|
0. Back
|
||||||
display_user_profile_data: |-
|
display_user_metadata: |-
|
||||||
END Your details are:
|
CON Your details are:
|
||||||
Name: %{full_name}
|
Name: %{full_name}
|
||||||
Gender: %{gender}
|
Gender: %{gender}
|
||||||
Location: %{location}
|
Location: %{location}
|
||||||
@ -85,7 +85,7 @@ en:
|
|||||||
retry: |-
|
retry: |-
|
||||||
CON Please enter your PIN. You have %{remaining_attempts} attempts remaining.
|
CON Please enter your PIN. You have %{remaining_attempts} attempts remaining.
|
||||||
0. Back
|
0. Back
|
||||||
standard_pin_authorization:
|
display_metadata_pin_authorization:
|
||||||
first: |-
|
first: |-
|
||||||
CON Please enter your PIN.
|
CON Please enter your PIN.
|
||||||
0. Back
|
0. Back
|
||||||
|
@ -56,7 +56,7 @@ sw:
|
|||||||
5. Angalia wasifu wako
|
5. Angalia wasifu wako
|
||||||
0. Nyuma
|
0. Nyuma
|
||||||
display_user_metadata: |-
|
display_user_metadata: |-
|
||||||
END Wasifu wako una maelezo yafuatayo:
|
CON Wasifu wako una maelezo yafuatayo:
|
||||||
Jina: %{full_name}
|
Jina: %{full_name}
|
||||||
Jinsia: %{gender}
|
Jinsia: %{gender}
|
||||||
Eneo: %{location}
|
Eneo: %{location}
|
||||||
|
@ -6,6 +6,7 @@ DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER=0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C
|
|||||||
DEV_ETH_ACCOUNT_RESERVE_MINTER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
|
DEV_ETH_ACCOUNT_RESERVE_MINTER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
|
||||||
DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
|
DEV_ETH_ACCOUNT_ACCOUNTS_INDEX_WRITER=${DEV_ETH_ACCOUNT_RESERVE_MINTER:-$DEV_ETH_ACCOUNT_CONTRACT_DEPLOYER}
|
||||||
DEV_RESERVE_AMOUNT=${DEV_ETH_RESERVE_AMOUNT:-""10000000000000000000000000000000000}
|
DEV_RESERVE_AMOUNT=${DEV_ETH_RESERVE_AMOUNT:-""10000000000000000000000000000000000}
|
||||||
|
faucet_amount=${DEV_FAUCET_AMOUNT:-0}
|
||||||
keystore_file=$(realpath ./keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c)
|
keystore_file=$(realpath ./keystore/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c)
|
||||||
|
|
||||||
echo "environment:"
|
echo "environment:"
|
||||||
@ -71,6 +72,8 @@ if [[ -n "${ETH_PROVIDER}" ]]; then
|
|||||||
# Sarafu faucet contract
|
# Sarafu faucet contract
|
||||||
>&2 echo "deploy token faucet contract"
|
>&2 echo "deploy token faucet contract"
|
||||||
DEV_FAUCET_ADDRESS=`sarafu-faucet-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w -v --account-index-address $DEV_ACCOUNT_INDEX_ADDRESS $DEV_RESERVE_ADDRESS`
|
DEV_FAUCET_ADDRESS=`sarafu-faucet-deploy -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -w -v --account-index-address $DEV_ACCOUNT_INDEX_ADDRESS $DEV_RESERVE_ADDRESS`
|
||||||
|
>&2 echo "set token faucet amount"
|
||||||
|
sarafu-faucet-set -y $keystore_file -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -a $DEV_FAUCET_ADDRESS $faucet_amount
|
||||||
eth-contract-registry-set -w -y $keystore_file -r $CIC_REGISTRY_ADDRESS -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -vv Faucet $DEV_FAUCET_ADDRESS
|
eth-contract-registry-set -w -y $keystore_file -r $CIC_REGISTRY_ADDRESS -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -vv Faucet $DEV_FAUCET_ADDRESS
|
||||||
>&2 echo "set faucet as token minter"
|
>&2 echo "set faucet as token minter"
|
||||||
giftable-token-minter -w -y $keystore_file -a $DEV_RESERVE_ADDRESS -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -vv $DEV_FAUCET_ADDRESS
|
giftable-token-minter -w -y $keystore_file -a $DEV_RESERVE_ADDRESS -i $CIC_CHAIN_SPEC -p $ETH_PROVIDER -vv $DEV_FAUCET_ADDRESS
|
||||||
|
@ -21,8 +21,6 @@ debug='-vv'
|
|||||||
abi_dir=${ETH_ABI_DIR:-/usr/local/share/cic/solidity/abi}
|
abi_dir=${ETH_ABI_DIR:-/usr/local/share/cic/solidity/abi}
|
||||||
gas_amount=100000000000000000000000
|
gas_amount=100000000000000000000000
|
||||||
token_amount=${gas_amount}
|
token_amount=${gas_amount}
|
||||||
#faucet_amount=1000000000
|
|
||||||
faucet_amount=${DEV_FAUCET_AMOUNT:-0}
|
|
||||||
env_out_file=${CIC_DATA_DIR}/.env_seed
|
env_out_file=${CIC_DATA_DIR}/.env_seed
|
||||||
init_level_file=${CIC_DATA_DIR}/.init
|
init_level_file=${CIC_DATA_DIR}/.init
|
||||||
truncate $env_out_file -s 0
|
truncate $env_out_file -s 0
|
||||||
|
Loading…
Reference in New Issue
Block a user