def compile_proto_stubs(org_id, service_id): boto_utils = BotoUtils(region_name=REGION_NAME) base_url = f"s3://{ASSETS_COMPONENT_BUCKET_NAME}/assets/{org_id}/{service_id}/proto.tar.gz" output_url = f"s3://{ASSETS_COMPONENT_BUCKET_NAME}/assets/{org_id}/{service_id}/" lambda_payload = { "input_s3_path": base_url, "output_s3_path": output_url, "org_id": org_id, "service_id": service_id } response = boto_utils.invoke_lambda( invocation_type="RequestResponse", lambda_function_arn=MANAGE_PROTO_COMPILATION, payload=json.dumps(lambda_payload)) generated_stubs_url = [] if response['statusCode'] == 200: output_bucket, output_key = boto_utils.get_bucket_and_key_from_url( url=f"{output_url}stubs") stub_objects = boto_utils.get_objects_from_s3(bucket=output_bucket, key=output_key) for object in stub_objects: generated_stubs_url.append( f"https://{output_bucket}.s3.{REGION_NAME}.amazonaws.com/{object['Key']}" ) return generated_stubs_url else: msg = f"Error generating stubs :: {response}" logger.info(msg) raise Exception(msg)
def __init__(self, repo): self.repo = repo self.boto_utils = BotoUtils(region_name=REGION_NAME) self.blockchain_util = BlockChainUtil( provider_type="HTTP_PROVIDER", provider=NETWORKS[NETWORK_ID]['http_provider']) self.utils = Utils() self.channel_dao = ChannelDAO(repo=self.repo) self.wallet_dao = WalletDAO(repo=self.repo)
class OrganizationOrchestratorService: def __init__(self): self.boto_client = BotoUtils(REGION_NAME) def register_org_member(self, username, payload): wallet_address = payload["wallet_address"] invite_code = payload["invite_code"] self.registry_register_org_member(username, wallet_address, invite_code) self.register_wallet(username, wallet_address) return "OK" def registry_register_org_member(self, username, wallet_address, invite_code): register_member_event = { "path": f"/org/member/register", "body": json.dumps({"wallet_address": wallet_address, "invite_code": invite_code}), "httpMethod": "POST", "requestContext": { "authorizer": { "claims": { "email": username } } } } logger.info(f"Requesting register user for invite_code: {invite_code} " f"username: {username} wallet_address:{wallet_address}") register_member_response = self.boto_client.invoke_lambda( lambda_function_arn=REGISTRY_ARN["REGISTER_MEMBER_ARN"], invocation_type='RequestResponse', payload=json.dumps(register_member_event) ) if register_member_response["statusCode"] != 201: raise Exception(f"Failed to register user for invite_code: {invite_code} " f"username: {username} wallet_address:{wallet_address}") def register_wallet(self, username, wallet_address, wallet_type="METAMASK"): register_wallet_body = { 'address': wallet_address, 'type': wallet_type, 'username': username } register_wallet_payload = { "path": "/wallet/register", "body": json.dumps(register_wallet_body), "httpMethod": "POST" } raw_response = self.boto_client.invoke_lambda(lambda_function_arn=WALLETS_SERVICE_ARN, invocation_type="RequestResponse", payload=json.dumps(register_wallet_payload)) status = raw_response["statusCode"] if int(status) != 200: raise Exception("Unable to register wallet for username %s", username)
def __init__(self, obj_repo): self.repo = obj_repo self.obj_transaction_history_dao = TransactionHistoryDAO(self.repo) self.lambda_client = boto3.client('lambda', region_name=REGION_NAME) self.boto_client = BotoUtils(REGION_NAME) self.wallet_service = WalletService() self.obj_blockchain_util = BlockChainUtil( provider_type="HTTP_PROVIDER", provider=NETWORKS[NETWORK_ID]['http_provider'] ) self.utils = Utils()
class UploadService: def __init__(self): self.boto_utils = BotoUtils(region_name=REGION_NAME) def store_file(self, upload_type, file_data, request_params, username): """ TODO: persist user history of the storage request """ if upload_type == UploadType.ORG_ASSETS.value: org_id = request_params["org_uuid"] bucket = UPLOAD_TYPE_DETAILS[upload_type]["bucket"] dest_file_path = UPLOAD_TYPE_DETAILS[upload_type][ "bucket_path"].format(org_id, date_time_for_filename(), file_data["file_extension"]) self.boto_utils.s3_upload_file(file_data["file_path"], bucket, dest_file_path) file_url = f"https://{bucket}.s3.amazonaws.com/{dest_file_path}" return file_url elif upload_type in [ UploadType.SERVICE_ASSETS.value, UploadType.SERVICE_GALLERY_IMAGES.value, UploadType.SERVICE_PAGE_COMPONENTS.value, UploadType.SERVICE_PROTO_FILES.value ]: org_id = request_params["org_uuid"] service_id = request_params["service_uuid"] bucket = UPLOAD_TYPE_DETAILS[upload_type]["bucket"] dest_file_path = UPLOAD_TYPE_DETAILS[upload_type][ "bucket_path"].format(org_id, service_id, date_time_for_filename(), file_data["file_extension"]) self.boto_utils.s3_upload_file(file_data["file_path"], bucket, dest_file_path) file_url = f"https://{bucket}.s3.amazonaws.com/{dest_file_path}" return file_url else: logger.error( f"Invalid upload request type {upload_type} params: {request_params}" ) raise BadRequestException()
def __make_trasaction(self, *positional_inputs, method_name): if self.__env_type == EnvironmentType.TEST.value: executor_key = BotoUtils(REGION_NAME).get_ssm_parameter( BLOCKCHAIN_TEST_ENV["publisher_private_key"]) transaction_object = self.__generate_blockchain_transaction_for_test_environment( *positional_inputs, method_name=method_name) else: raise EnvironmentNotFoundException() raw_transaction = self.__blockchain_util.sign_transaction_with_private_key( transaction_object=transaction_object, private_key=executor_key) transaction_hash = self.__blockchain_util.process_raw_transaction( raw_transaction=raw_transaction) return transaction_hash
class WalletService: def __init__(self, repo): self.repo = repo self.boto_utils = BotoUtils(region_name=REGION_NAME) self.blockchain_util = BlockChainUtil( provider_type="HTTP_PROVIDER", provider=NETWORKS[NETWORK_ID]['http_provider']) self.utils = Utils() self.channel_dao = ChannelDAO(repo=self.repo) self.wallet_dao = WalletDAO(repo=self.repo) def create_and_register_wallet(self, username): address, private_key = self.blockchain_util.create_account() wallet = Wallet(address=address, private_key=private_key, type=GENERAL_WALLET_TYPE, status=WalletStatus.ACTIVE.value) self._register_wallet(wallet, username) return wallet.to_dict() def _register_wallet(self, wallet, username): existing_wallet = self.wallet_dao.get_wallet_details(wallet) if len(existing_wallet) == 0: self.wallet_dao.insert_wallet(wallet) self.wallet_dao.add_user_for_wallet(wallet, username) def register_wallet(self, wallet_address, wallet_type, status, username): wallet = Wallet(address=wallet_address, type=wallet_type, status=status) self._register_wallet(wallet, username) return wallet.to_dict() def remove_user_wallet(self, username): self.wallet_dao.remove_user_wallet(username) def get_wallet_details(self, username): """ Method to get wallet details for a given username. """ logger.info(f"Fetching wallet details for {username}") wallet_data = self.wallet_dao.get_wallet_data_by_username(username) self.utils.clean(wallet_data) logger.info( f"Fetched {len(wallet_data)} wallets for username: {username}") wallet_response = {"username": username, "wallets": wallet_data} return wallet_response def __generate_signature_details(self, recipient, group_id, agi_tokens, expiration, message_nonce, signer_key): data_types = [ "string", "address", "address", "address", "address", "bytes32", "uint256", "uint256", "uint256" ] values = [ "__openChannelByThirdParty", self.mpe_address, self.EXECUTOR_WALLET_ADDRESS, SIGNER_ADDRESS, recipient, group_id, agi_tokens, expiration, message_nonce ] signature = self.blockchain_util.generate_signature( data_types=data_types, values=values, signer_key=signer_key) v, r, s = Web3.toInt( hexstr="0x" + signature[-2:]), signature[:66], "0x" + signature[66:130] return r, s, v, signature def __calculate_amount_in_cogs(self, amount, currency): if currency == "USD": amount_in_cogs = round(amount) else: raise Exception("Currency %s not supported.", currency) return amount_in_cogs def record_create_channel_event(self, payload): current_time = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") if not self.channel_dao.persist_create_channel_event( payload, current_time): raise Exception("Failed to create record") return {} def open_channel_by_third_party(self, order_id, sender, signature, r, s, v, group_id, org_id, amount, currency, recipient, current_block_no, amount_in_cogs): self.EXECUTOR_WALLET_ADDRESS = self.boto_utils.get_ssm_parameter( EXECUTOR_ADDRESS) self.EXECUTOR_WALLET_KEY = self.boto_utils.get_ssm_parameter( EXECUTOR_KEY) method_name = "openChannelByThirdParty" self.mpe_address = self.blockchain_util.read_contract_address( net_id=NETWORK_ID, path=MPE_ADDR_PATH, key='address') # 1 block no is mined in 15 sec on average, setting expiration as 10 years expiration = current_block_no + (10 * 365 * 24 * 60 * 4) # amount_in_cogs = self.__calculate_amount_in_cogs(amount=amount, currency=currency) self.__validate__cogs(amount_in_cogs=amount_in_cogs) group_id_in_hex = "0x" + base64.b64decode(group_id).hex() positional_inputs = (sender, SIGNER_ADDRESS, recipient, group_id_in_hex, amount_in_cogs, expiration, current_block_no, v, r, s) transaction_object = self.blockchain_util.create_transaction_object( *positional_inputs, method_name=method_name, address=self.EXECUTOR_WALLET_ADDRESS, contract_path=MPE_CNTRCT_PATH, contract_address_path=MPE_ADDR_PATH, net_id=NETWORK_ID) raw_transaction = self.blockchain_util.sign_transaction_with_private_key( transaction_object=transaction_object, private_key=self.EXECUTOR_WALLET_KEY) transaction_hash = self.blockchain_util.process_raw_transaction( raw_transaction=raw_transaction) logger.info( "openChannelByThirdParty::transaction_hash : %s for order_id : %s", transaction_hash, order_id) self.channel_dao.insert_channel_history( order_id=order_id, amount=amount, currency=currency, group_id=group_id, org_id=org_id, type=method_name, recipient=recipient, address=sender, signature=signature, request_parameters=str(positional_inputs), transaction_hash=transaction_hash, status=TransactionStatus.PENDING) return { "transaction_hash": transaction_hash, "signature": signature, "amount_in_cogs": amount_in_cogs, "type": method_name } def set_default_wallet(self, username, address): self.wallet_dao.set_default_wallet(username=username, address=address) return "OK" def add_funds_to_channel(self, org_id, group_id, channel_id, sender, recipient, order_id, amount, currency, amount_in_cogs): self.EXECUTOR_WALLET_ADDRESS = self.boto_utils.get_ssm_parameter( EXECUTOR_ADDRESS) self.EXECUTOR_WALLET_KEY = self.boto_utils.get_ssm_parameter( EXECUTOR_KEY) method_name = "channelAddFunds" # amount_in_cogs = self.__calculate_amount_in_cogs(amount=amount, currency=currency) self.__validate__cogs(amount_in_cogs=amount_in_cogs) positional_inputs = (channel_id, amount_in_cogs) transaction_object = self.blockchain_util.create_transaction_object( *positional_inputs, method_name=method_name, address=self.EXECUTOR_WALLET_ADDRESS, contract_path=MPE_CNTRCT_PATH, contract_address_path=MPE_ADDR_PATH, net_id=NETWORK_ID) raw_transaction = self.blockchain_util.sign_transaction_with_private_key( transaction_object=transaction_object, private_key=self.EXECUTOR_WALLET_KEY) transaction_hash = self.blockchain_util.process_raw_transaction( raw_transaction=raw_transaction) logger.info("channelAddFunds::transaction_hash: %s for order_id: %s", transaction_hash, order_id) self.channel_dao.insert_channel_history( order_id=order_id, amount=amount, currency=currency, group_id=group_id, org_id=org_id, type=method_name, recipient=recipient, address=sender, signature=None, request_parameters=str(positional_inputs), transaction_hash=transaction_hash, status=TransactionStatus.PENDING) return { "transaction_hash": transaction_hash, "amount_in_cogs": amount_in_cogs, "type": method_name } def get_transactions_from_username_recipient(self, username, org_id, group_id): logger.info( f"Fetching transactions for {username} to org_id: {org_id} group_id: {org_id}" ) channel_data = self.channel_dao.get_channel_transactions_for_username_recipient( username=username, group_id=group_id, org_id=org_id) self.utils.clean(channel_data) logger.info(f"Fetched {len(channel_data)} transactions") transaction_details = {"username": username, "wallets": []} wallet_transactions = dict() for rec in channel_data: sender_address = rec["address"] if rec["address"] not in wallet_transactions: wallet_transactions[rec["address"]] = { "address": sender_address, "is_default": rec["is_default"], "type": rec["type"], "transactions": [] } if rec['recipient'] is None: continue transaction = { "org_id": org_id, "group_id": group_id, "recipient": rec["recipient"], "amount": rec["amount"], "transaction_type": rec["transaction_type"], "currency": rec["currency"], "status": rec["status"], "created_at": rec["created_at"], } wallet_transactions[sender_address]["transactions"].append( transaction) for key in wallet_transactions: wallet = wallet_transactions[key] transaction_details["wallets"].append(wallet) return transaction_details def get_channel_transactions_against_order_id(self, order_id): transaction_history = self.channel_dao.get_channel_transactions_against_order_id( order_id) for record in transaction_history: record["created_at"] = record["created_at"].strftime( "%Y-%m-%d %H:%M:%S") return {"order_id": order_id, "transactions": transaction_history} def __validate__cogs(self, amount_in_cogs): if amount_in_cogs < MINIMUM_AMOUNT_IN_COGS_ALLOWED: raise Exception( "Insufficient amount to buy minimum amount in cogs allowed.")
def __init__(self, obj_repo): self.repo = obj_repo self.obj_utils = Utils() self.ssm_client = boto3.client('ssm') self.boto_client = BotoUtils(region_name=REGION_NAME)
import tempfile import uuid from pathlib import Path import pkg_resources from grpc_tools.protoc import main as protoc from common import utils from common.boto_utils import BotoUtils from common.logger import get_logger from contract_api.config import REGION_NAME from utility.config import SLACK_HOOK from utility.exceptions import ProtoNotFound TEMP_FILE_DIR = tempfile.gettempdir() boto_utils = BotoUtils(region_name=REGION_NAME) logger = get_logger(__name__) def generate_python_stubs(input_s3_path, output_s3_path): try: input_bucket, input_key = boto_utils.get_bucket_and_key_from_url( url=input_s3_path) if output_s3_path: output_bucket, output_key = boto_utils.get_bucket_and_key_from_url( url=output_s3_path) tmp_paths = initialize_temp_paths() boto_utils.download_folder_contents_from_s3(bucket=input_bucket, key=input_key, target=tmp_paths["base"]) proto_location = None
class UserService: def __init__(self): self.user_factory = UserFactory() self.user_repo = UserRepository() self.boto_client = BotoUtils(REGION_NAME) def add_or_update_user_preference(self, payload, username): user_preference_list = self.user_factory.parse_raw_user_preference_data( payload=payload) response = [] for user_preference in user_preference_list: if user_preference.status and user_preference.opt_out_reason is not None: raise Exception("Invalid Payload.") user_data = self.user_repo.get_user_data_for_given_username( username=username) if len(user_data) == 0: raise Exception("User is not registered.") if user_preference.status is False: self.user_repo.disable_preference( user_preference=user_preference, user_row_id=user_data[0]["row_id"]) response.append(Status.DISABLED.value) else: self.user_repo.enable_preference( user_preference=user_preference, user_row_id=user_data[0]["row_id"]) response.append(Status.ENABLED.value) return response def get_user_preference(self, username): user_data = self.user_repo.get_user_data_for_given_username( username=username) if len(user_data) == 0: raise Exception("User is not registered.") user_preference_raw_data = self.user_repo.get_user_preferences( user_row_id=user_data[0]["row_id"]) preferences = self.user_factory.parse_user_preference_raw_data( user_preference_raw_data) return [preference.to_dict() for preference in preferences] def delete_user(self, username): self.user_repo.delete_user(username) self._unlink_wallets_from_user(username) def _unlink_wallets_from_user(self, username): delete_user_wallet_event = { "path": "/wallet/delete", "queryStringParameters": { "username": username }, "httpMethod": "POST" } delete_user_wallet_response = self.boto_client.invoke_lambda( lambda_function_arn=DELETE_USER_WALLET_ARN, invocation_type='RequestResponse', payload=json.dumps(delete_user_wallet_event)) logger.info(f"create_channel_response {delete_user_wallet_response}") if delete_user_wallet_response["statusCode"] != 201: raise Exception(f"Failed to delete user wallet") def _get_no_of_free_calls_from_daemon(self, email, token_to_get_free_call, expiry_date_block, signature, current_block_number, daemon_endpoint): request = state_service_pb2.FreeCallStateRequest() request.user_id = email request.token_for_free_call = token_to_get_free_call request.token_expiry_date_block = expiry_date_block request.signature = signature request.current_block = current_block_number endpoint_object = urlparse(daemon_endpoint) if endpoint_object.port is not None: channel_endpoint = endpoint_object.hostname + ":" + str( endpoint_object.port) else: channel_endpoint = endpoint_object.hostname if endpoint_object.scheme == "http": channel = grpc.insecure_channel(channel_endpoint) elif endpoint_object.scheme == "https": channel = grpc.secure_channel( channel_endpoint, grpc.ssl_channel_credentials(root_certificates=certificate)) else: raise ValueError( 'Unsupported scheme in service metadata ("{}")'.format( endpoint_object.scheme)) stub = state_service_pb2_grpc.FreeCallStateServiceStub(channel) response = stub.GetFreeCallsAvailable(request) logger.info( f"No of free free call for {email} {daemon_endpoint} {current_block_number} is {response.free_calls_available}" ) return response.free_calls_available def get_free_call(self, event): # passing event here as metering contract is that it need the entire event object # metering will eventually go out then we will clean this up. try: payload_dict = event['queryStringParameters'] email = payload_dict['username'] lambda_client = boto3.client('lambda') org_id = payload_dict['organization_id'] service_id = payload_dict['service_id'] group_id = unquote(payload_dict['group_id']) response = lambda_client.invoke( FunctionName=GET_SIGNATURE_TO_GET_FREE_CALL_FROM_DAEMON, InvocationType='RequestResponse', Payload=json.dumps({ "queryStringParameters": { "username": email, "org_id": org_id, "service_id": service_id, "group_id": group_id } })) result = json.loads(response.get('Payload').read()) signature_response = json.loads(result['body']) if signature_response["status"] == "success": logger.info( f"Got signature to make free call to daemon for {email} : {signature_response['data']}" ) token_to_get_free_call = signature_response["data"].get( "token_to_get_free_call", "") expiry_date_block = signature_response["data"].get( "expiry_date_block", "") signature = signature_response["data"].get("signature", "") current_block_number = signature_response["data"].get( "current_block_number", "") daemon_endpoint = signature_response["data"].get( "daemon_endpoint", "") free_calls_allowed = signature_response["data"].get( "free_calls_allowed", 0) free_call_available = self._get_no_of_free_calls_from_daemon( email, bytes.fromhex(token_to_get_free_call), expiry_date_block, bytes.fromhex(signature), current_block_number, daemon_endpoint) response = { "username": email, "org_id": org_id, "service_id": service_id, "total_calls_made": free_calls_allowed - free_call_available, "free_calls_allowed": free_calls_allowed } return generate_lambda_response(200, response, cors_enabled=True) else: raise Exception( "Error while getting signature to make free call to daemon" ) except Exception as e: logger.info( f"Failed to get freecall from daemon {email} {org_id} {service_id} error {str(e)}" ) lambda_client = boto3.client('lambda') response = lambda_client.invoke( FunctionName=GET_FREE_CALLS_METERING_ARN, InvocationType='RequestResponse', Payload=json.dumps(event)) result = json.loads(response.get('Payload').read()) return result def register_user(self, user_attribute, client_id): user = self.user_factory.create_user_domain_model( payload=user_attribute, client_id=client_id) if not user.email_verified: raise EmailNotVerifiedException() return self.user_repo.register_user_data(user)
def __init__(self): self.user_factory = UserFactory() self.user_repo = UserRepository() self.boto_client = BotoUtils(REGION_NAME)
class OrderService: def __init__(self, obj_repo): self.repo = obj_repo self.obj_transaction_history_dao = TransactionHistoryDAO(self.repo) self.lambda_client = boto3.client('lambda', region_name=REGION_NAME) self.boto_client = BotoUtils(REGION_NAME) self.wallet_service = WalletService() self.obj_blockchain_util = BlockChainUtil( provider_type="HTTP_PROVIDER", provider=NETWORKS[NETWORK_ID]['http_provider'] ) self.utils = Utils() def initiate_order(self, username, payload_dict): """ Initiate Order Step 1 Order Creation Step 2 Initiate Payment Step 3 Persist Transaction History """ price = payload_dict["price"] order_type = payload_dict["item_details"]["order_type"] item_details = payload_dict["item_details"] group_id = item_details["group_id"] org_id = item_details["org_id"] channel_id = "" amount_in_cogs = self.calculate_amount_in_cogs(amount=price["amount"], currency=price["currency"]) if amount_in_cogs < 1: raise Exception("Amount in cogs should be greater than equal to 1") item_details["amount_in_cogs"] = amount_in_cogs if order_type == OrderType.CREATE_WALLET_AND_CHANNEL.value: item_details["wallet_address"] = "" recipient = self.get_payment_address_for_org(group_id=group_id, org_id=org_id) elif order_type == OrderType.CREATE_CHANNEL.value: recipient = self.get_payment_address_for_org(group_id=group_id, org_id=org_id) elif order_type == OrderType.FUND_CHANNEL.value: channel = self.get_channel_for_topup(username=username, group_id=group_id, org_id=org_id) if channel is None: raise Exception(f"Channel not found for the user: {username} with org: {org_id} group: {group_id}") recipient = channel["recipient"] channel_id = channel["channel_id"] item_details["wallet_address"] = channel["address"] else: raise Exception("Invalid order type") item_details["channel_id"] = channel_id item_details["recipient"] = recipient order_details = self.manage_create_order( username=username, item_details=item_details, price=price ) order_id = order_details["order_id"] try: payment_data = self.manage_initiate_payment( username=username, order_id=order_id, price=price, payment_method=payload_dict["payment_method"] ) payment_id = payment_data["payment_id"] raw_payment_data = json.dumps(payment_data["payment"]) obj_transaction_history = TransactionHistory( username=username, order_id=order_id, order_type=order_type, payment_id=payment_id, raw_payment_data=raw_payment_data, status=Status.PAYMENT_INITIATED.value ) self.obj_transaction_history_dao.insert_transaction_history(obj_transaction_history=obj_transaction_history) return payment_data except Exception as e: obj_transaction_history = TransactionHistory( username=username, order_id=order_id, order_type=order_type, status=Status.PAYMENT_INITIATION_FAILED.value ) self.obj_transaction_history_dao.insert_transaction_history(obj_transaction_history=obj_transaction_history) print(repr(e)) raise e def get_channel_for_topup(self, username, group_id, org_id): channel_details = self.wallet_service.get_channel_details( username=username, group_id=group_id, org_id=org_id ) wallets = channel_details["wallets"] for wallet in wallets: if (wallet["type"] == "GENERAL") and len(wallet["channels"]) > 0: if wallet["channels"][0]["signer"] == SIGNER_ADDRESS: wallet_address = wallet["address"] channel = wallet["channels"][0] channel["address"] = wallet_address return channel return None def get_payment_address_for_org(self, org_id, group_id): group_details_event = { "path": f"/org/{org_id}/group/{quote(group_id, safe='')}", "pathParameters": { "orgId": org_id, "group_id": quote(group_id, safe='') }, "httpMethod": "GET" } logger.info(f"get_group_for_org request: {org_id} and {group_id}") group_details_lambda_response = self.lambda_client.invoke( FunctionName=GET_GROUP_FOR_ORG_API_ARN, InvocationType='RequestResponse', Payload=json.dumps(group_details_event) ) group_details_response = json.loads(group_details_lambda_response.get('Payload').read()) logger.info(f"get_group_for_org response: {group_details_response}") if group_details_response["statusCode"] != 200: raise Exception(f"Failed to fetch group details for org_id:{org_id} " f"group_id {group_id}") group_details_response_body = json.loads(group_details_response["body"]) groups = group_details_response_body["data"]["groups"] if len(groups) == 0: raise Exception(f"Failed to find group {group_id} for org_id: {org_id}") return groups[0]["payment"]["payment_address"] def calculate_amount_in_cogs(self, amount, currency): if currency == "USD": amount_in_cogs = round(amount * USD_TO_COGS_CONVERSION_FACTOR) return amount_in_cogs else: raise Exception("Currency %s not supported.", currency) def execute_order(self, username, payload_dict): """ Execute Order Step 1 Execute Payment Step 2 Get Receipient Address Step 3 Process Order Step 4 Update Transaction History """ order_id = payload_dict["order_id"] payment_id = payload_dict["payment_id"] order = self.get_order_details_by_order_id(order_id, username) payment = None for payment_item in order["payments"]: if payment_item["payment_id"] == payment_id: payment = payment_item break if payment is None: raise Exception(f"Failed to fetch order details for order_id {order_id} \n" f"payment_id {payment_id} \n" f"username{username}") order_type = order["item_details"]["order_type"] item_details = order["item_details"] payment_method = payment["payment_details"]["payment_method"] paid_payment_details = payload_dict["payment_details"] price = payment["price"] status = Status.PAYMENT_EXECUTION_FAILED.value self.manage_execute_payment( username=username, order_id=order_id, payment_id=payment_id, payment_details=paid_payment_details, payment_method=payment_method ) status = Status.PAYMENT_EXECUTED.value try: status = Status.ORDER_PROCESSING_FAILED.value amount_in_cogs = self.calculate_amount_in_cogs(amount=price["amount"], currency=price["currency"]) if amount_in_cogs < 1: raise Exception("Amount in cogs should be greater than equal to 1") processed_order_data = self.manage_process_order( username=username, order_id=order_id, order_type=order_type, amount=price["amount"], currency=price["currency"], order_data=item_details, amount_in_cogs=amount_in_cogs ) status = Status.ORDER_PROCESSED.value obj_transaction_history = TransactionHistory( username=username, order_id=order_id, order_type=order_type, status=status, payment_id=payment_id, payment_method=payment_method, raw_payment_data=json.dumps(paid_payment_details) ) self.obj_transaction_history_dao.insert_transaction_history(obj_transaction_history=obj_transaction_history) processed_order_data["price"] = price processed_order_data["item_details"] = item_details return processed_order_data except Exception as e: obj_transaction_history = TransactionHistory( username=username, order_id=order_id, order_type=order_type, status=status ) self.obj_transaction_history_dao.insert_transaction_history(obj_transaction_history=obj_transaction_history) print(repr(e)) raise e def get_order_details_by_order_id(self, order_id, username): order_details_event = { "path": f"order/{order_id}", "pathParameters": {"order_id": order_id}, "httpMethod": "GET" } logger.info(f"Requesting order details for order_id {order_id}") response = self.lambda_client.invoke( FunctionName=ORDER_DETAILS_ORDER_ID_ARN, InvocationType='RequestResponse', Payload=json.dumps(order_details_event) ) order_details_response = json.loads(response.get('Payload').read()) if order_details_response["statusCode"] != 200: raise Exception(f"Failed to fetch order details for order_id {order_id} username{username}") order_details_data = json.loads(order_details_response["body"]) if order_details_data["username"] != username: raise Exception(f"Failed to fetch order details for order_id {order_id} username{username}") return order_details_data def manage_initiate_payment(self, username, order_id, price, payment_method): initiate_payment_event = { "pathParameters": {"order_id": order_id}, "httpMethod": "POST", "body": json.dumps({"price": price, "payment_method": payment_method}) } response = self.lambda_client.invoke( FunctionName=INITIATE_PAYMENT_SERVICE_ARN, InvocationType='RequestResponse', Payload=json.dumps(initiate_payment_event) ) initiate_payment_data = json.loads(response.get('Payload').read()) if initiate_payment_data["statusCode"] == 201: return json.loads(initiate_payment_data["body"]) else: logger.error("Error initiating payment for user %s", username) raise PaymentInitiateFailed def manage_create_order(self, username, item_details, price): create_order_event = { "path": "/order/create", "httpMethod": "POST", "body": json.dumps({"price": price, "item_details": item_details, "username": username}) } create_order_service_response = self.boto_client.invoke_lambda( lambda_function_arn=CREATE_ORDER_SERVICE_ARN, invocation_type='RequestResponse', payload=json.dumps(create_order_event) ) logger.info(f"create_order_service_response: {create_order_service_response}") if create_order_service_response["statusCode"] == 201: return json.loads(create_order_service_response["body"]) else: raise Exception(f"Error creating order for user {username}") def manage_execute_payment(self, username, order_id, payment_id, payment_details, payment_method): execute_payment_event = { "pathParameters": {"order_id": order_id, "payment_id": payment_id}, "body": json.dumps({"payment_method": payment_method, "payment_details": payment_details}) } response = self.lambda_client.invoke( FunctionName=EXECUTE_PAYMENT_SERVICE_ARN, InvocationType='RequestResponse', Payload=json.dumps(execute_payment_event) ) payment_executed = json.loads(response.get('Payload').read()) if payment_executed["statusCode"] == 201: return payment_executed else: raise Exception(f"Error executing payment for username {username} against order_id {order_id}") def manage_process_order(self, username, order_id, order_type, amount, currency, order_data, amount_in_cogs): logger.info(f"Order Data {order_data}") group_id = order_data["group_id"] org_id = order_data["org_id"] recipient = order_data["recipient"] channel_id = order_data["channel_id"] sender = order_data["wallet_address"] if order_type == OrderType.CREATE_WALLET_AND_CHANNEL.value: wallet_create_payload = { "path": "/wallet", "body": json.dumps({"username": username}), "httpMethod": "POST" } wallet_create_lambda_response = self.lambda_client.invoke( FunctionName=WALLETS_SERVICE_ARN, InvocationType='RequestResponse', Payload=json.dumps(wallet_create_payload) ) wallet_create_response = json.loads(wallet_create_lambda_response.get("Payload").read()) if wallet_create_response["statusCode"] != 200: raise Exception("Failed to create wallet") wallet_create_response_body = json.loads(wallet_create_response["body"]) wallet_details = wallet_create_response_body["data"] try: current_block_no = self.obj_blockchain_util.get_current_block_no() # 1 block no is mined in 15 sec on average, setting expiration as 10 years expiration = current_block_no + (10 * 365 * 24 * 60 * 4) message_nonce = current_block_no self.EXECUTOR_WALLET_ADDRESS = self.boto_client.get_ssm_parameter(EXECUTOR_ADDRESS) group_id_in_hex = "0x" + base64.b64decode(group_id).hex() signature_details = self.generate_signature_for_open_channel_for_third_party( recipient=recipient, group_id=group_id_in_hex, amount_in_cogs=amount_in_cogs, expiration=expiration, message_nonce=message_nonce, sender_private_key=wallet_details["private_key"], executor_wallet_address=self.EXECUTOR_WALLET_ADDRESS ) logger.info(f"Signature Details {signature_details}") open_channel_body = { 'order_id': order_id, 'sender': wallet_details["address"], 'signature': signature_details["signature"], 'r': signature_details["r"], 's': signature_details["s"], 'v': signature_details["v"], 'group_id': group_id, 'org_id': org_id, 'amount': amount, 'currency': currency, 'recipient': recipient, 'current_block_no': current_block_no, 'amount_in_cogs': amount_in_cogs } channel_details = self.wallet_service.create_channel(open_channel_body=open_channel_body) channel_details.update(wallet_details) return channel_details except Exception as e: logger.error("Failed to create channel") logger.error(repr(e)) response = { "transaction_hash": "", "signature": "", "amount_in_cogs": 0, "price": { "amount": amount, "currency": currency }, "item_details": order_data } response.update(wallet_details) raise ChannelCreationFailed("Failed to create channel", wallet_details=response) elif order_type == OrderType.CREATE_CHANNEL.value: try: logger.info(f"Order Data {order_data}") signature = order_data["signature"] v, r, s = Web3.toInt(hexstr="0x" + signature[-2:]), signature[:66], "0x" + signature[66:130] open_channel_body = { 'order_id': order_id, 'sender': order_data["wallet_address"], 'signature': order_data["signature"], 'r': r, 's': s, 'v': v, 'group_id': group_id, 'org_id': org_id, 'amount': amount, 'currency': currency, 'recipient': recipient, 'current_block_no': order_data["current_block_number"], 'amount_in_cogs': amount_in_cogs } channel_details = self.wallet_service.create_channel(open_channel_body=open_channel_body) logger.info("channel_details: ", channel_details) return channel_details except Exception as e: logger.error("Failed to create channel") logger.error(repr(e)) raise ChannelCreationFailed("Failed to create channel", wallet_details=order_data) elif order_type == OrderType.FUND_CHANNEL.value: try: fund_channel_body = { 'order_id': order_id, 'group_id': group_id, 'org_id': org_id, 'amount': amount, 'channel_id': channel_id, 'currency': currency, 'recipient': recipient, 'sender': sender, 'amount_in_cogs': amount_in_cogs } fund_channel_payload = { "path": "/wallet/channel/deposit", "body": json.dumps(fund_channel_body), "httpMethod": "POST" } fund_channel_lambda_response = self.lambda_client.invoke( FunctionName=WALLETS_SERVICE_ARN, InvocationType='RequestResponse', Payload=json.dumps(fund_channel_payload) ) fund_channel_response = json.loads(fund_channel_lambda_response.get("Payload").read()) if fund_channel_response["statusCode"] != 200: raise Exception(f"Failed to add funds in channel for {fund_channel_body}") fund_channel_response_body = json.loads(fund_channel_response["body"]) fund_channel_transaction_details = fund_channel_response_body["data"] return fund_channel_transaction_details except Exception as e: logger.error("Failed to fund channel") logger.error(repr(e)) raise FundChannelFailed() else: raise Exception("Order type is not valid.") def get_order_details_by_username(self, username): order_details_event = { "path": f"/order", "queryStringParameters": {"username": username}, "httpMethod": "GET" } logger.info(f"Requesting order details for username {username}") order_details_response = self.boto_client.invoke_lambda( lambda_function_arn=ORDER_DETAILS_BY_USERNAME_ARN, invocation_type='RequestResponse', payload=json.dumps(order_details_event) ) if order_details_response["statusCode"] != 200: raise Exception(f"Failed to fetch order details for username{username}") org_id_name_mapping = self.get_organizations_from_contract() order_details_response_body = json.loads(order_details_response["body"]) orders = order_details_response_body["orders"] for order in orders: order_id = order["order_id"] order["wallet_type"] = "GENERAL" if "org_id" in order["item_details"]: org_id = order["item_details"]["org_id"] if org_id in org_id_name_mapping: order["item_details"]["organization_name"] = org_id_name_mapping[org_id] transaction_details_event = { "path": f"/wallet/channel/transactions", "queryStringParameters": {"order_id": order_id}, "httpMethod": "GET" } transaction_details_lambda_response = self.lambda_client.invoke( FunctionName=WALLETS_SERVICE_ARN, InvocationType='RequestResponse', Payload=json.dumps(transaction_details_event) ) transaction_details_response = json.loads(transaction_details_lambda_response.get('Payload').read()) if transaction_details_response["statusCode"] != 200: raise Exception(f"Failed to fetch transaction details for username{order_id}") transaction_details_response_body = json.loads(transaction_details_response["body"]) order["wallet_transactions"] = transaction_details_response_body["data"]["transactions"] order_status = TransactionStatus.SUCCESS for payment in order["payments"]: if payment["payment_status"] != TransactionStatus.SUCCESS: order_status = payment["payment_status"] break for wallet_transaction in order["wallet_transactions"]: if wallet_transaction["status"] != TransactionStatus.SUCCESS: order_status = wallet_transaction["status"] break order["order_status"] = order_status return {"orders": orders} def get_organizations_from_contract(self): org_details_event = { "path": f"/org", "httpMethod": "GET" } org_details_response = self.boto_client.invoke_lambda( lambda_function_arn=GET_ALL_ORG_API_ARN, invocation_type='RequestResponse', payload=json.dumps(org_details_event) ) if org_details_response["statusCode"] != 200: raise Exception("Failed to get org details") org_details = json.loads(org_details_response["body"])["data"] org_id_name_mapping = {} for org in org_details: org_id_name_mapping[org["org_id"]] = org["org_name"] return org_id_name_mapping def generate_signature_for_open_channel_for_third_party(self, recipient, group_id, amount_in_cogs, expiration, message_nonce, sender_private_key, executor_wallet_address): signature_for_open_channel_for_third_party_body = { 'recipient': recipient, 'group_id': group_id, 'amount_in_cogs': amount_in_cogs, 'expiration': expiration, 'message_nonce': message_nonce, 'signer_key': sender_private_key, 'executor_wallet_address': executor_wallet_address } signature_for_open_channel_for_third_party_payload = { "path": "/signer/open-channel-for-third-party", "body": json.dumps(signature_for_open_channel_for_third_party_body), "httpMethod": "POST" } signature_for_open_channel_for_third_party_response = self.lambda_client.invoke( FunctionName=SIGNER_SERVICE_ARN, InvocationType='RequestResponse', Payload=json.dumps(signature_for_open_channel_for_third_party_payload) ) signature_response = json.loads(signature_for_open_channel_for_third_party_response.get("Payload").read()) if signature_response["statusCode"] != 200: raise Exception(f"Failed to create signature for {signature_for_open_channel_for_third_party_body}") signature_details = json.loads(signature_response["body"]) return signature_details["data"] def cancel_order(self): logger.info("Start of UpdateTransactionStatus::manage_update_canceled_order_in_txn_history") list_of_order_id_for_expired_transaction = self.obj_transaction_history_dao.get_order_id_for_expired_transaction() logger.info(f"List of order_id to be updated with ORDER CANCELED: {list_of_order_id_for_expired_transaction}") update_transaction_status = self.obj_transaction_history_dao.update_transaction_status( list_of_order_id=list_of_order_id_for_expired_transaction, status=OrderStatus.ORDER_CANCELED.value) return update_transaction_status def cancel_order_for_given_order_id(self, order_id): logger.info("UpdateTransactionStatus::cancel_order_for_given_order_id: %s", order_id) transaction_data_dict = self.obj_transaction_history_dao.get_transaction_details_for_given_order_id( order_id=order_id) if transaction_data_dict["status"] == OrderStatus.ORDER_CANCELED.value: return f"Order with order_id {order_id} is already canceled." elif transaction_data_dict["status"] in [OrderStatus.PAYMENT_INITIATED.value, OrderStatus.PAYMENT_INITIATION_FAILED.value, OrderStatus.PAYMENT_EXECUTION_FAILED]: self.obj_transaction_history_dao.update_transaction_status(list_of_order_id=[order_id], status=OrderStatus.ORDER_CANCELED.value) return f"Order with order_id {order_id} is canceled successfully." else: return f"Unable to cancel order with order_id {order_id}" def currency_to_token(self, amount, currency): amount_in_cogs = self.calculate_amount_in_cogs(amount=decimal.Decimal(amount), currency=currency) conversion_data = {"base": currency, "amount": amount, "amount_in_cogs": str(amount_in_cogs), "amount_in_agi": str(self.utils.cogs_to_agi(cogs=amount_in_cogs)), f"{currency}/cogs": str(USD_TO_COGS_CONVERSION_FACTOR), "agi/cogs": str(COGS_TO_AGI)} logger.debug(f"currency_to_token::conversion_data {conversion_data}") return conversion_data
class OrganizationPublisherService: def __init__(self, org_uuid, username): self.org_uuid = org_uuid self.username = username self.boto_utils = BotoUtils(region_name=registry.config.REGION_NAME) def get_approval_pending_organizations(self, limit, type=None): status = OrganizationStatus.ONBOARDING.value organizations = org_repo.get_organizations(status, limit, type) return [org.to_response() for org in organizations] def get_all_org_for_user(self): logger.info(f"get organization for user: {self.username}") organizations = org_repo.get_all_orgs_for_user(username=self.username) return [org.to_response() for org in organizations] def get_all_org_id(self): organizations = org_repo.get_organizations() return [org.id for org in organizations] def get_org_id_availability_status(self, org_id): org_id_list = self.get_all_org_id() if org_id in org_id_list: return OrganizationIDAvailabilityStatus.UNAVAILABLE.value if RegistryBlockChainUtil( EnvironmentType.MAIN.value).is_org_published(org_id): return OrganizationIDAvailabilityStatus.UNAVAILABLE.value return OrganizationIDAvailabilityStatus.AVAILABLE.value def get_groups_for_org(self): logger.info(f"get groups for org_uuid: {self.org_uuid}") groups = org_repo.get_groups_for_org(self.org_uuid) return { "org_uuid": self.org_uuid, "groups": [group.to_response() for group in groups] } def create_organization(self, payload): logger.info(f"create organization for user: {self.username}") organization = OrganizationFactory.org_domain_entity_from_payload( payload) organization.setup_id() logger.info(f"assigned org_uuid : {organization.uuid}") org_ids = self.get_all_org_id() if organization.id in org_ids: raise Exception("Org_id already exists") updated_state = Organization.next_state( None, None, OrganizationActions.CREATE.value) org_repo.add_organization(organization, self.username, updated_state) organization = org_repo.get_organization(org_id=organization.id) return organization.to_response() def update_organization(self, payload, action): logger.info( f"update organization for user: {self.username} org_uuid: {self.org_uuid} action: {action}" ) updated_organization = OrganizationFactory.org_domain_entity_from_payload( payload) current_organization = org_repo.get_organization( org_uuid=self.org_uuid) self._archive_current_organization(current_organization) updated_state = Organization.next_state(current_organization, updated_organization, action) org_repo.update_organization(updated_organization, self.username, updated_state) return "OK" def notify_user_on_start_of_onboarding_process(self, org_id, recipients): if not recipients: logger.info( f"Unable to find recipients for organization with org_id {org_id}" ) return mail_template = get_notification_mail_template_for_service_provider_when_org_is_submitted_for_onboarding( org_id) for recipient in recipients: send_notification_payload = { "body": json.dumps({ "message": mail_template["body"], "subject": mail_template["subject"], "notification_type": "support", "recipient": recipient }) } self.boto_utils.invoke_lambda( lambda_function_arn=registry.config.NOTIFICATION_ARN, invocation_type="RequestResponse", payload=json.dumps(send_notification_payload)) logger.info( f"Recipient {recipient} notified for successfully starting onboarding process." ) def _archive_current_organization(self, organization): if organization.get_status() == OrganizationStatus.PUBLISHED.value: org_repo.add_organization_archive(organization) def publish_org_to_ipfs(self): logger.info(f"publish organization to ipfs org_uuid: {self.org_uuid}") organization = org_repo.get_organization(org_uuid=self.org_uuid) organization.publish_to_ipfs() org_repo.store_ipfs_hash(organization, self.username) return organization.to_response() def save_transaction_hash_for_publish_org(self, payload): transaction_hash = payload.get("transaction_hash") if transaction_hash is None: raise BadRequestException() user_address = payload.get("wallet_address") nonce = payload.get("nonce") logger.info( f"save transaction hash for publish organization org_uuid: {self.org_uuid} " f"transaction_hash: {transaction_hash} user_address: {user_address} nonce: {nonce}" ) org_repo.persist_publish_org_transaction_hash(self.org_uuid, transaction_hash, user_address, nonce, self.username) return "OK" def get_all_member(self, status, role, pagination_details): offset = pagination_details.get("offset", None) limit = pagination_details.get("limit", None) sort = pagination_details.get("sort", None) org_members_list = org_repo.get_org_member(org_uuid=self.org_uuid, status=status, role=role) return [member.to_response() for member in org_members_list] def get_member(self, member_username): members = org_repo.get_org_member(username=member_username, org_uuid=self.org_uuid) if len(members) == 0: logger.info( f"No member {member_username} for the organization {self.org_uuid}" ) return [] return [member.to_response() for member in members] def verify_invite(self, invite_code): logger.info( f"verify member invite_code: {invite_code} username: {self.username}" ) if org_repo.org_member_verify(self.username, invite_code): return "OK" return "NOT_FOUND" def delete_members(self, org_members): logger.info( f"user: {self.username} requested to delete members: {org_members} of org_uuid: {self.org_uuid}" ) org_member_list = OrganizationFactory.org_member_domain_entity_from_payload_list( org_members, self.org_uuid) org_repo.delete_members(org_member_list, member_status=[ OrganizationMemberStatus.PENDING.value, OrganizationMemberStatus.ACCEPTED.value ]) return "OK" def publish_members(self, transaction_hash, org_members): logger.info( f"user: {self.username} published members: {org_members} with transaction_hash: {transaction_hash}" ) org_member = OrganizationFactory.org_member_domain_entity_from_payload_list( org_members, self.org_uuid) org_repo.persist_publish_org_member_transaction_hash( org_member, transaction_hash, self.org_uuid) return "OK" def register_member(self, invite_code, wallet_address): logger.info( f"register user: {self.username} with invite_code: {invite_code}") if Web3.isAddress(wallet_address): org_repo.update_org_member(self.username, wallet_address, invite_code) else: raise Exception("Invalid wallet address") return "OK" def invite_members(self, members_payload): current_time = datetime.utcnow() requested_invite_member_list = OrganizationFactory.org_member_domain_entity_from_payload_list( members_payload, self.org_uuid) current_org_member = org_repo.get_org_member(org_uuid=self.org_uuid) current_org_member_username_list = [ member.username for member in current_org_member ] eligible_invite_member_list = [ member for member in requested_invite_member_list if member.username not in current_org_member_username_list ] for org_member in eligible_invite_member_list: org_member.generate_invite_code() org_member.set_status(OrganizationMemberStatus.PENDING.value) org_member.set_role(Role.MEMBER.value) org_member.set_invited_on(current_time) org_member.set_updated_on(current_time) organization = org_repo.get_organization(org_uuid=self.org_uuid) org_name = organization.name self._send_email_notification_for_inviting_organization_member( eligible_invite_member_list, org_name) org_repo.add_member(eligible_invite_member_list) failed_invitation = [ member.username for member in requested_invite_member_list if member.username in current_org_member_username_list ] return { "member": [member.to_response() for member in eligible_invite_member_list], "failed_invitation": failed_invitation } def _send_email_notification_for_inviting_organization_member( self, org_members_list, org_name): for org_member in org_members_list: recipient = org_member.username mail_template = get_org_member_invite_mail(org_name, org_member.invite_code) send_notification_payload = { "body": json.dumps({ "message": mail_template["body"], "subject": mail_template["subject"], "notification_type": "support", "recipient": recipient }) } self.boto_utils.invoke_lambda( lambda_function_arn=registry.config.NOTIFICATION_ARN, invocation_type="RequestResponse", payload=json.dumps(send_notification_payload)) logger.info(f"Org Membership Invite sent to {recipient}") def update_verification(self, verification_type, verification_details): if verification_type in ORG_TYPE_VERIFICATION_TYPE_MAPPING: if ORG_TYPE_VERIFICATION_TYPE_MAPPING[ verification_type] == OrganizationType.INDIVIDUAL.value: owner_username = verification_details["username"] status = verification_details["status"] updated_by = verification_details["updated_by"] org_repo.update_all_individual_organization_for_user( owner_username, status, updated_by) elif ORG_TYPE_VERIFICATION_TYPE_MAPPING[ verification_type] == OrganizationType.ORGANIZATION.value: status = verification_details["status"] org_uuid = verification_details["org_uuid"] updated_by = verification_details["updated_by"] comment = verification_details["comment"] if status in ORG_STATUS_LIST: org_repo.update_organization_status( org_uuid, status, updated_by) organization = org_repo.get_organization(org_uuid=org_uuid) owner = org_repo.get_org_member(org_uuid=org_uuid, role=Role.OWNER.value) owner_username = owner[0].username self.send_mail_to_owner(owner_username, comment, organization.id, status) else: logger.error(f"Invalid status {status}") raise MethodNotImplemented() else: logger.error( f"Invalid organization type with verification type {verification_type}" ) raise MethodNotImplemented() else: logger.error(f"Invalid verification type {verification_type}") raise MethodNotImplemented() return {} def send_mail_to_owner(self, owner_email_address, comment, org_id, status): if status == OrganizationStatus.REJECTED.value: mail_template = get_owner_mail_for_org_rejected(org_id, comment) elif status == OrganizationStatus.CHANGE_REQUESTED.value: mail_template = get_owner_mail_for_org_changes_requested( org_id, comment) elif status == OrganizationStatus.APPROVED.value: mail_template = get_owner_mail_for_org_approved(org_id) else: logger.info(f"Organization status: {status}") raise InvalidOrganizationStateException() utils.send_email_notification([owner_email_address], mail_template["subject"], mail_template["body"], registry.config.NOTIFICATION_ARN, self.boto_utils)
def __init__(self): self.boto_utils = BotoUtils(region_name=REGION_NAME)
class WalletService: def __init__(self): self.boto_client = BotoUtils(REGION_NAME) def create_channel(self, open_channel_body): create_channel_transaction_payload = { "path": "/wallet/channel/event", "body": json.dumps(open_channel_body), "httpMethod": "POST" } create_channel_response = self.boto_client.invoke_lambda( lambda_function_arn=CREATE_CHANNEL_EVENT_ARN, invocation_type='RequestResponse', payload=json.dumps(create_channel_transaction_payload)) logger.info(f"create_channel_response {create_channel_response}") if create_channel_response["statusCode"] != 201: raise Exception(f"Failed to create channel") create_channel_response_body = json.loads( create_channel_response["body"]) channel_details = create_channel_response_body["data"] return channel_details def get_channel_details(self, username, org_id, group_id): """ Method to get wallet details for a given username. """ try: wallet_channel_transactions = self.get_channel_transactions( username=username, org_id=org_id, group_id=group_id) wallet_response = { "username": username, "org_id": org_id, "group_id": group_id, "wallets": wallet_channel_transactions } for wallet in wallet_response["wallets"]: user_address = wallet["address"] wallet["channels"] = self.get_channels_from_contract( user_address=user_address, org_id=org_id, group_id=group_id) return wallet_response except Exception as e: print(repr(e)) raise e def get_channel_transactions(self, username, org_id, group_id): channel_transactions_event = { "path": "/wallet/channel/transactions", "queryStringParameters": { "username": username, "group_id": group_id, "org_id": org_id }, "httpMethod": "GET" } channel_transactions_response = self.boto_client.invoke_lambda( lambda_function_arn=WALLETS_SERVICE_ARN, invocation_type='RequestResponse', payload=json.dumps(channel_transactions_event)) if channel_transactions_response["statusCode"] != 200: raise Exception( f"Failed to fetch wallet details for username: {username}") channel_transactions_response_body = json.loads( channel_transactions_response["body"]) channel_transactions = channel_transactions_response_body["data"][ "wallets"] return channel_transactions def get_channels_from_contract(self, user_address, org_id, group_id): event = { "httpMethod": "GET", "path": "/channel", "queryStringParameters": { "user_address": user_address, "org_id": org_id, "group_id": group_id } } channel_details_response = self.boto_client.invoke_lambda( lambda_function_arn=GET_CHANNEL_API_OLD_ARN, invocation_type="RequestResponse", payload=json.dumps(event)) if "statusCode" not in channel_details_response: logger.error( f"contract API boto call failed {channel_details_response}") raise Exception( f"Failed to get channel details from contract API {event}") if channel_details_response["statusCode"] != 200: raise Exception( f"Failed to get channel details from contract API username: {user_address} " f"group_id: {group_id} " f"org_id: {org_id}") channel_details = json.loads(channel_details_response["body"])["data"] return channel_details["channels"] def get_wallets(self, username): get_wallet_event = { "path": "/wallet", "queryStringParameters": { "username": username }, "httpMethod": "GET" } get_wallet_response = self.boto_client.invoke_lambda( lambda_function_arn=WALLETS_SERVICE_ARN, invocation_type="RequestResponse", payload=json.dumps(get_wallet_event)) status = get_wallet_response["statusCode"] if status != 200: raise Exception("Unable to get wallets for username %s", username) wallets = json.loads(get_wallet_response["body"])["data"] return wallets def register_wallet(self, username, wallet_details): register_wallet_body = { 'address': wallet_details["address"], 'type': wallet_details["type"], 'username': username } register_wallet_payload = { "path": "/wallet/register", "body": json.dumps(register_wallet_body), "httpMethod": "POST" } raw_response = self.boto_client.invoke_lambda( lambda_function_arn=WALLETS_SERVICE_ARN, invocation_type="RequestResponse", payload=json.dumps(register_wallet_payload)) status = raw_response["statusCode"] if int(status) != 200: raise Exception("Unable to register wallet for username %s", username) return json.loads(raw_response["body"])["data"] def set_default_wallet(self, username, address): set_default_wallet_body = {'address': address, 'username': username} set_default_wallet_payload = { "path": "/wallet/status", "body": json.dumps(set_default_wallet_body), "httpMethod": "POST" } response = self.boto_client.invoke_lambda( lambda_function_arn=WALLETS_SERVICE_ARN, invocation_type="RequestResponse", payload=json.dumps(set_default_wallet_payload)) return json.loads(response["body"])["data"] def get_default_wallet(self, username): wallets = self.get_wallets(username)["wallets"] default_wallet = None for wallet in wallets: if wallet["is_default"] == 1 and wallet["type"] == "GENERAL": default_wallet = wallet if default_wallet is None: raise Exception("No active paypal wallet") return default_wallet
def __init__(self, org_uuid, username): self.org_uuid = org_uuid self.username = username self.boto_utils = BotoUtils(region_name=REGION_NAME)
class PaypalPayment(Payment): def __init__(self, payment_id, amount, currency, payment_status, created_at, payment_details): super().__init__(payment_id, amount, currency, payment_status, created_at, payment_details) self.boto_utils = BotoUtils(region_name=REGION_NAME) def initiate_payment(self, order_id, item_details): try: payee_client_api = paypalrestsdk.Api({ 'mode': MODE, 'client_id': self.boto_utils.get_ssm_parameter(PAYPAL_CLIENT), 'client_secret': self.boto_utils.get_ssm_parameter(PAYPAL_SECRET) }) except Exception as e: logger.error("Failed to get ssm parameters") raise e paypal_payload = self.get_paypal_payload(order_id, item_details["org_id"], item_details["service_id"]) payment = paypalrestsdk.Payment(paypal_payload, api=payee_client_api) if not payment.create(): logger.error(f"Paypal error:{payment.error}") raise Exception("Payment failed to create") logger.info(f"Paypal payment initiated with paypal_payment_id: {payment.id}") approval_url = "" for link in payment.links: if link.rel == "approval_url": approval_url = str(link.href) if len(approval_url) == 0: raise Exception("Payment link not found") self._payment_details["payment_id"] = payment.id response_payload = { "payment": { "id": payment.id, "payment_url": approval_url } } return response_payload def execute_transaction(self, paid_payment_details): try: payee_client_api = paypalrestsdk.Api({ 'mode': MODE, 'client_id': self.boto_utils.get_ssm_parameter(PAYPAL_CLIENT), 'client_secret': self.boto_utils.get_ssm_parameter(PAYPAL_SECRET) }) except Exception as e: logger.error("Failed to get ssm parameters") raise e paypal_payment_id = self._payment_details["payment_id"] payer_id = paid_payment_details["payer_id"] payment = paypalrestsdk.Payment.find(paypal_payment_id, api=payee_client_api) if payment.execute({"payer_id": payer_id}): logger.info(f"Paypal payment execution is success for paypal_payment_id:{paypal_payment_id}") self._payment_status = PaymentStatus.SUCCESS return True elif self._payment_status == PaymentStatus.PENDING: logger.info(f"Paypal payment execution is failed for paypal_payment_id:{paypal_payment_id}") self._payment_status = PaymentStatus.FAILED logger.error(payment.error) return False def get_paypal_payload(self, order_id, org_id, service_id): paypal_payload = { "intent": "sale", "payer": { "payment_method": PAYMENT_METHOD_PAYPAL }, "redirect_urls": { "return_url": PAYMENT_RETURN_URL.format(org_id, service_id, order_id, self._payment_id), "cancel_url": PAYMENT_CANCEL_URL.format(org_id, service_id, order_id, self._payment_id) }, "transactions": [ { "item_list": { "items": [ { "name": "item", "sku": "item", "price": self._amount, "currency": self._currency, "quantity": 1 } ] }, "amount": { "total": self._amount, "currency": self._currency }, "description": "" } ] } return paypal_payload
class OrganizationPublisherService: def __init__(self, org_uuid, username): self.org_uuid = org_uuid self.username = username self.boto_utils = BotoUtils(region_name=REGION_NAME) def get_for_admin(self, params): status = params.get("status", None) organizations = org_repo.get_org(status) return [org.to_response() for org in organizations] def get_all_org_for_user(self): logger.info(f"get organization for user: {self.username}") organizations = org_repo.get_org_for_user(username=self.username) return [org.to_response() for org in organizations] def get_groups_for_org(self): logger.info(f"get groups for org_uuid: {self.org_uuid}") groups = org_repo.get_groups_for_org(self.org_uuid) return { "org_uuid": self.org_uuid, "groups": [group.to_response() for group in groups] } def create_organization(self, payload): logger.info(f"create organization for user: {self.username}") organization = OrganizationFactory.org_domain_entity_from_payload( payload) organization.setup_id() logger.info(f"assigned org_uuid : {organization.uuid}") org_repo.add_organization(organization, self.username, OrganizationStatus.ONBOARDING.value) return "OK" def save_organization_draft(self, payload): logger.info( f"edit organization for user: {self.username} org_uuid: {self.org_uuid}" ) updated_organization = OrganizationFactory.org_domain_entity_from_payload( payload) current_organization = org_repo.get_org_for_org_uuid(self.org_uuid) self._archive_current_organization(current_organization) if current_organization.is_minor(updated_organization): org_repo.update_organization(updated_organization, self.username, OrganizationStatus.DRAFT.value) else: raise MethodNotImplemented() return "OK" def _archive_current_organization(self, organization): if organization.get_status() == OrganizationStatus.PUBLISHED.value: org_repo.add_organization_archive(organization) def submit_organization_for_approval(self, payload): logger.info( f"submit for approval organization org_uuid: {self.org_uuid}") organization = OrganizationFactory.org_domain_entity_from_payload( payload) if not organization.is_valid(): raise Exception("Invalid org metadata") org_repo.store_organization(organization, self.username, OrganizationStatus.APPROVED.value) return "OK" def publish_org_to_ipfs(self): logger.info(f"publish organization to ipfs org_uuid: {self.org_uuid}") organization = org_repo.get_org_for_org_uuid(self.org_uuid) organization.publish_to_ipfs() org_repo.store_ipfs_hash(organization, self.username) return organization.to_response() def save_transaction_hash_for_publish_org(self, payload): transaction_hash = payload["transaction_hash"] user_address = payload["wallet_address"] logger.info( f"save transaction hash for publish organization org_uuid: {self.org_uuid} " f"transaction_hash: {transaction_hash} user_address: {user_address}" ) org_repo.persist_publish_org_transaction_hash(self.org_uuid, transaction_hash, user_address, self.username) return "OK" def get_all_member(self, status, role, pagination_details): offset = pagination_details.get("offset", None) limit = pagination_details.get("limit", None) sort = pagination_details.get("sort", None) org_members_list = org_repo.get_org_member(org_uuid=self.org_uuid, status=status, role=role) return [member.to_response() for member in org_members_list] def get_member(self, member_username): members = org_repo.get_org_member(username=member_username, org_uuid=self.org_uuid) if len(members) == 0: logger.info( f"No member {member_username} for the organization {self.org_uuid}" ) return [] return [member.to_response() for member in members] def verify_invite(self, invite_code): logger.info( f"verify member invite_code: {invite_code} username: {self.username}" ) if org_repo.org_member_verify(self.username, invite_code): return "OK" return "NOT_FOUND" def delete_members(self, org_members): logger.info( f"user: {self.username} requested to delete members: {org_members} of org_uuid: {self.org_uuid}" ) org_member_list = OrganizationFactory.org_member_domain_entity_from_payload_list( org_members, self.org_uuid) org_repo.delete_members(org_member_list) return "OK" def publish_members(self, transaction_hash, org_members): logger.info( f"user: {self.username} published members: {org_members} with transaction_hash: {transaction_hash}" ) org_member = OrganizationFactory.org_member_domain_entity_from_payload_list( org_members, self.org_uuid) org_repo.persist_publish_org_member_transaction_hash( org_member, transaction_hash, self.org_uuid) return "OK" def register_member(self, invite_code, wallet_address): logger.info( f"register user: {self.username} with invite_code: {invite_code}") if Web3.isAddress(wallet_address): org_repo.update_org_member(self.username, wallet_address, invite_code) else: raise Exception("Invalid wallet address") return "OK" def invite_members(self, members_payload): current_time = datetime.utcnow() requested_invite_member_list = OrganizationFactory.org_member_domain_entity_from_payload_list( members_payload, self.org_uuid) current_org_member = org_repo.get_org_member(org_uuid=self.org_uuid) current_org_member_username_list = [ member.username for member in current_org_member ] eligible_invite_member_list = [ member for member in requested_invite_member_list if member.username not in current_org_member_username_list ] for org_member in eligible_invite_member_list: org_member.generate_invite_code() org_member.set_status(OrganizationMemberStatus.PENDING.value) org_member.set_role(Role.MEMBER.value) org_member.set_invited_on(current_time) org_member.set_updated_on(current_time) organization = org_repo.get_org_for_org_uuid(self.org_uuid) org_name = organization.name self._send_email_notification_for_inviting_organization_member( eligible_invite_member_list, org_name) org_repo.add_member(eligible_invite_member_list) failed_invitation = [ member.username for member in requested_invite_member_list if member.username in current_org_member_username_list ] return { "member": [member.to_response() for member in eligible_invite_member_list], "failed_invitation": failed_invitation } def _send_email_notification_for_inviting_organization_member( self, org_members_list, org_name): for org_member in org_members_list: recipient = org_member.username org_member_notification_subject = self._get_org_member_notification_subject( org_name) org_member_notification_message = self._get_org_member_notification_message( org_member.invite_code, org_name) send_notification_payload = { "body": json.dumps({ "message": org_member_notification_message, "subject": org_member_notification_subject, "notification_type": "support", "recipient": recipient }) } self.boto_utils.invoke_lambda( lambda_function_arn=NOTIFICATION_ARN, invocation_type="RequestResponse", payload=json.dumps(send_notification_payload)) logger.info(f"Org Membership Invite sent to {recipient}") @staticmethod def _get_org_member_notification_message(invite_code, org_name): return f"<html><head></head><body><div><p>Hello,</p><p>Organization {org_name} has sent you membership invite. " \ f"Your invite code is <strong>{invite_code}</strong>.</p><br/><p>Please click on the link below to " \ f"accept the invitation.</p><p>{PUBLISHER_PORTAL_DAPP_URL}</p><br/><br/><p>" \ "<em>Please do not reply to the email for any enquiries for any queries please email at " \ "[email protected].</em></p><p>Warmest regards, <br />SingularityNET Marketplace " \ "Team</p></div></body></html>" @staticmethod def _get_org_member_notification_subject(org_name): return f"Membership Invitation from Organization {org_name}"
def __init__(self, event, networks, net_id): self.event = event self.networks = networks self.net_id = net_id self.boto_utils = BotoUtils(REGION_NAME)
class User: def __init__(self, obj_repo): self.repo = obj_repo self.obj_utils = Utils() self.boto_client = BotoUtils(region_name=REGION_NAME) def _set_user_data(self, user_data, origin): """ Method to set user information. """ try: claims = user_data['authorizer']['claims'] email_verified = claims['email_verified'] status = 0 if email_verified: status = 1 else: raise Exception("Email verification is pending.") q_dta = [claims['email'], user_data['accountId'], origin, claims['nickname'], claims['email'], status, status, user_data['requestId'], user_data['requestTimeEpoch'], dt.utcnow(), dt.utcnow()] set_usr_dta = self.repo.execute( "INSERT INTO user (username, account_id, origin, name, email, email_verified, status, request_id, " "request_time_epoch, row_created, row_updated) " "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", q_dta) if len(set_usr_dta) > 0: return "success" else: return "User already exist" except Exception as e: print(repr(e)) raise e def _fetch_private_key_from_ssm(self, address): try: store = self.boto_client.get_ssm_parameter(parameter=PATH_PREFIX + str(address)) return store['Parameter']['Value'] except Exception as e: print(repr(e)) raise Exception("Error fetching value from parameter store.") def user_signup(self, user_data, origin): """ Method to assign pre-seeded wallet to user. This is one time process. """ try: username = user_data['authorizer']['claims']['email'] set_user_data = self._set_user_data(user_data, origin) print(set_user_data) return set_user_data except Exception as e: self.repo.rollback_transaction() print(repr(e)) raise e def get_user_profile(self, user_data): """ Method to fetch user profile data. """ try: username = user_data['authorizer']['claims']['email'] result = self.repo.execute( "SELECT * FROM user WHERE username = %s", [username]) self.obj_utils.clean(result) return {"success": "success", "data": result} except Exception as e: print(repr(e)) raise e def update_user_profile(self, email_alerts, is_terms_accepted, user_data): """ Method to update user profile data. """ try: username = user_data['authorizer']['claims']['email'] result = self.repo.execute("UPDATE user SET email_alerts = %s, is_terms_accepted = %s WHERE username = %s", [int(email_alerts is True), int(is_terms_accepted is True), username]) return {"success": "success", "data": []} except Exception as e: print(repr(e)) raise e def validate_and_set_user_feedback(self, feedback_data, user_data): """ Method to validate and set user feedback data. """ schema = Schema([{'org_id': And(str), 'service_id': And(str), 'user_rating': And(str), 'comment': And(str) }]) try: feedback_data = schema.validate([feedback_data]) feedback_recorded = self._set_user_feedback( feedback_data[0], user_data=user_data) if feedback_recorded: return [] return None except Exception as err: print("Invalid Input ", err) return None def get_user_feedback(self, user_data, org_id, service_id): """ Method to get user feedback data. """ try: user_rating_dict = {} username = user_data['authorizer']['claims']['email'] query_part = "" query_part_values = [] if org_id is not None: query_part = "AND org_id = %s " query_part_values.append(org_id) if service_id is not None: query_part += "AND service_id = %s " query_part_values.append(service_id) rating_query = "SELECT * FROM user_service_vote WHERE username = %s " + query_part rating = self.repo.execute( rating_query, [username] + query_part_values) self.obj_utils.clean(rating) feedback_query = "SELECT * FROM user_service_feedback WHERE username = %s " + query_part feedback = self.repo.execute( feedback_query, [username] + query_part_values) self.obj_utils.clean(feedback) for record in feedback: org_id = record['org_id'] service_id = record['service_id'] if org_id not in user_rating_dict.keys(): user_rating_dict[org_id] = {} if service_id not in user_rating_dict.keys(): user_rating_dict[org_id][service_id] = {} user_rating_dict[org_id][service_id]['comment'] = [] user_rating_dict[org_id][service_id]['comment'].append( record['comment']) for record in rating: org_id = record['org_id'] service_id = record['service_id'] record.update({'comment': user_rating_dict.get(org_id, {}) .get(service_id, {}) .get("comment", [])}) return rating except Exception as e: print(repr(e)) raise e def _set_user_feedback(self, feedback_data, user_data): """ Method to set user rating and feedback. """ try: user_rating = str(feedback_data['user_rating']) if float(user_rating) > 5.0 or float(user_rating) < 1.0: raise Exception( "Invalid Rating. Provided user rating should be between 1.0 and 5.0 .") curr_dt = dt.utcnow() username = user_data['authorizer']['claims']['email'] org_id = feedback_data['org_id'] service_id = feedback_data['service_id'] comment = feedback_data['comment'] self.repo.begin_transaction() set_rating = "INSERT INTO user_service_vote (username, org_id, service_id, rating, row_updated, row_created) " \ "VALUES (%s, %s, %s, %s, %s, %s) " \ "ON DUPLICATE KEY UPDATE rating = %s, row_updated = %s" set_rating_params = [username, org_id, service_id, user_rating, curr_dt, curr_dt, user_rating, curr_dt] self.repo.execute(set_rating, set_rating_params) set_feedback = "INSERT INTO user_service_feedback (username, org_id, service_id, comment, row_updated, row_created)" \ "VALUES (%s, %s, %s, %s, %s, %s)" set_feedback_params = [username, org_id, service_id, comment, curr_dt, curr_dt] self.repo.execute(set_feedback, set_feedback_params) self._update_service_rating(org_id=org_id, service_id=service_id) self.repo.commit_transaction() return True except Exception as e: self.repo.rollback_transaction() print(repr(e)) raise e def _update_service_rating(self, org_id, service_id): """ Method updates service_rating and total_user_rated when user rating is changed for given service_id and org_id. """ try: update_service_metadata = self.repo.execute( "UPDATE service_metadata A INNER JOIN (SELECT U.org_id, U.service_id, AVG(U.rating) AS service_rating, " "count(*) AS total_users_rated FROM user_service_vote AS U WHERE U.rating IS NOT NULL GROUP BY " "U.service_id, U.org_id ) AS B ON A.org_id=B.org_id AND A.service_id=B.service_id SET A.service_rating " "= CONCAT('{\"rating\":', B.service_rating, ' , \"total_users_rated\":', B.total_users_rated, '}') " "WHERE A.org_id = %s AND A.service_id = %s ", [org_id, service_id]) except Exception as e: print(repr(e)) raise e
class OrganizationOrchestratorService: def __init__(self): self.boto_client = BotoUtils(REGION_NAME) def register_org_member(self, username, payload): wallet_address = payload["wallet_address"] invite_code = payload["invite_code"] self.registry_register_org_member(username, wallet_address, invite_code) self.register_wallet(username, wallet_address) return "OK" def registry_register_org_member(self, username, wallet_address, invite_code): register_member_event = { "path": f"/org/member/register", "body": json.dumps({ "wallet_address": wallet_address, "invite_code": invite_code }), "httpMethod": "POST", "requestContext": { "authorizer": { "claims": { "email": username } } } } logger.info(f"Requesting register user for invite_code: {invite_code} " f"username: {username} wallet_address:{wallet_address}") register_member_response = self.boto_client.invoke_lambda( lambda_function_arn=REGISTRY_ARN["REGISTER_MEMBER_ARN"], invocation_type='RequestResponse', payload=json.dumps(register_member_event)) if register_member_response["statusCode"] != 201: raise Exception( f"Failed to register user for invite_code: {invite_code} " f"username: {username} wallet_address:{wallet_address}") def register_wallet(self, username, wallet_address, wallet_type="METAMASK"): register_wallet_body = { 'address': wallet_address, 'type': wallet_type, 'username': username } register_wallet_payload = { "path": "/wallet/register", "body": json.dumps(register_wallet_body), "httpMethod": "POST" } raw_response = self.boto_client.invoke_lambda( lambda_function_arn=WALLETS_SERVICE_ARN, invocation_type="RequestResponse", payload=json.dumps(register_wallet_payload)) status = raw_response["statusCode"] if int(status) != 200: raise Exception("Unable to register wallet for username %s", username) def create_and_initiate_verification(self, create_org_details, username): org_details = self.create_org(create_org_details, username) org_uuid = org_details["org_uuid"] org_type = org_details["org_type"] if org_type == OrganizationType.ORGANIZATION.value: self.initiate_verification(org_uuid, VerificationType.DUNS.value, username) elif org_type == OrganizationType.INDIVIDUAL.value: self.initiate_verification(username, VerificationType.JUMIO.value, username) else: raise Exception( f"Verification initiate failed for Invalid org type {org_type}" ) self.notify_approval_team(org_details['org_id'], org_details['org_name']) self.notify_user_on_start_of_onboarding_process( org_id=org_details["org_id"], recipients=[username]) return org_details def notify_approval_team(self, org_id, org_name): slack_msg = f"Organization with org_id {org_id} is submitted for approval" mail_template = get_org_approval_mail(org_id, org_name) self.send_slack_message(slack_msg) send_email_notification([ORG_APPROVERS_DLIST], mail_template["subject"], mail_template["body"], NOTIFICATION_ARN, self.boto_client) def notify_user_on_start_of_onboarding_process(self, org_id, recipients): if not recipients: logger.info( f"Unable to find recipients for organization with org_id {org_id}" ) return mail_template = get_mail_template_to_user_for_org_onboarding(org_id) for recipient in recipients: send_notification_payload = { "body": json.dumps({ "message": mail_template["body"], "subject": mail_template["subject"], "notification_type": "support", "recipient": recipient }) } self.boto_client.invoke_lambda( lambda_function_arn=NOTIFICATION_ARN, invocation_type="RequestResponse", payload=json.dumps(send_notification_payload)) logger.info( f"Recipient {recipient} notified for successfully starting onboarding process." ) def send_slack_message(self, slack_msg): slack_url = SLACK_HOOK['hostname'] + SLACK_HOOK['path'] utils.send_slack_notification( slack_msg=slack_msg, slack_url=slack_url, slack_channel=SLACK_CHANNEL_FOR_APPROVAL_TEAM) def initiate_verification(self, entity_id, verification_type, username): if verification_type == VerificationType.JUMIO.value: initiate_verification_payload = { "requestContext": { "authorizer": { "claims": { "email": entity_id } } }, "body": json.dumps({"type": verification_type}) } elif verification_type == VerificationType.DUNS.value: initiate_verification_payload = { "requestContext": { "authorizer": { "claims": { "email": username } } }, "body": json.dumps({ "type": verification_type, "entity_id": entity_id }) } else: raise Exception( f"Verification initiate failed for Invalid verification type {verification_type}" ) raw_response = self.boto_client.invoke_lambda( lambda_function_arn=VERIFICATION_ARN["INITIATE"], invocation_type="RequestResponse", payload=json.dumps(initiate_verification_payload)) status = raw_response["statusCode"] if status != 201: raise Exception("Failed to create Organization") def create_org(self, org_details, username): create_organization_payload = { "requestContext": { "authorizer": { "claims": { "email": username } } }, "body": json.dumps(org_details) } raw_response = self.boto_client.invoke_lambda( lambda_function_arn=REGISTRY_ARN["CREATE_ORG_ARN"], invocation_type="RequestResponse", payload=json.dumps(create_organization_payload)) status = raw_response["statusCode"] if status != 200: raise Exception("Failed to create Organization") return json.loads(raw_response["body"])["data"]
import re import subprocess import tempfile import uuid from pathlib import Path, PurePath import pkg_resources from grpc_tools.protoc import main as protoc from snet import snet_cli from common import utils from common.boto_utils import BotoUtils from utility.config import PROTO_DIRECTORY_REGEX_PATTERN, PROTO_STUB_TARGET_LANGUAGES TEMP_FILE_DIR = tempfile.gettempdir() boto_utils = BotoUtils(region_name=None) class GenerateStubService: def __init__(self): pass def generate_service_proto_stubs(self, proto_s3_url, stub_s3_url): try: proto_bucket, proto_bucket_key = boto_utils.get_bucket_and_key_from_url( url=proto_s3_url) stub_bucket, stub_bucket_key = boto_utils.get_bucket_and_key_from_url( url=stub_s3_url) to_delete_objects = boto_utils.get_objects_from_s3( bucket=stub_bucket, key=stub_bucket_key)
def __init__(self, payment_id, amount, currency, payment_status, created_at, payment_details): super().__init__(payment_id, amount, currency, payment_status, created_at, payment_details) self.boto_utils = BotoUtils(region_name=REGION_NAME)
class UserService: def __init__(self): self.user_factory = UserFactory() self.user_repo = UserRepository() self.boto_client = BotoUtils(REGION_NAME) def add_or_update_user_preference(self, payload, username): user_preference_list = self.user_factory.parse_raw_user_preference_data( payload=payload) response = [] for user_preference in user_preference_list: if user_preference.status and user_preference.opt_out_reason is not None: raise Exception("Invalid Payload.") user_data = self.user_repo.get_user_data_for_given_username( username=username) if len(user_data) == 0: raise Exception("User is not registered.") if user_preference.status is False: self.user_repo.disable_preference( user_preference=user_preference, user_row_id=user_data[0]["row_id"]) response.append(Status.DISABLED.value) else: self.user_repo.enable_preference( user_preference=user_preference, user_row_id=user_data[0]["row_id"]) response.append(Status.ENABLED.value) return response def get_user_preference(self, username): user_data = self.user_repo.get_user_data_for_given_username( username=username) if len(user_data) == 0: raise Exception("User is not registered.") user_preference_raw_data = self.user_repo.get_user_preferences( user_row_id=user_data[0]["row_id"]) preferences = self.user_factory.parse_user_preference_raw_data( user_preference_raw_data) return [preference.to_dict() for preference in preferences] def delete_user(self, username): self.user_repo.delete_user(username) self._unlink_wallets_from_user(username) def _unlink_wallets_from_user(self, username): delete_user_wallet_event = { "path": "/wallet/delete", "queryStringParameters": { "username": username }, "httpMethod": "POST" } delete_user_wallet_response = self.boto_client.invoke_lambda( lambda_function_arn=DELETE_USER_WALLET_ARN, invocation_type='RequestResponse', payload=json.dumps(delete_user_wallet_event)) logger.info(f"create_channel_response {delete_user_wallet_response}") if delete_user_wallet_response["statusCode"] != 201: raise Exception(f"Failed to delete user wallet")
def __init__(self): self.boto_client = BotoUtils(REGION_NAME)
import requests from common.logger import get_logger from utility.infrastructure.repository.historical_crypto_fiat_rate import HistoricalCryptoFiatRates from utility.infrastructure.repository.crypto_fiat_rate import CryptoFiatRates from utility.infrastructure.models import HistoricalCryptoFiatExchangeRates, CryptoFiatExchangeRates from utility.config import CRYPTO_FIAT_CONVERSION, SLACK_HOOK from datetime import datetime from common.boto_utils import BotoUtils from common.utils import Utils rates = HistoricalCryptoFiatRates() logger = get_logger(__name__) boto_client = BotoUtils(region_name='us-east-1') def cmc_rate_converter(crypto_symbol, fiat_symbol): try: api_token = boto_client.get_parameter_value_from_secrets_manager( secret_name='COIN_MARKETPLACE_API_TOKEN') URL = CRYPTO_FIAT_CONVERSION['COINMARKETCAP']['API_ENDPOINT'].format( fiat_symbol, crypto_symbol) headers = {'X-CMC_PRO_API_KEY': api_token} result = requests.get(url=URL, headers=headers) response = result.json()['data'][0] fiat_rate = response['amount'] crypto_rate = response['quote'][fiat_symbol]['price'] logger.info(f"rates_from_cmc response: {response}") return crypto_symbol, crypto_rate, fiat_rate, fiat_symbol except Exception as e: