# Path: pyledger/server/handlers.py
# def handle_request(payload: bytes):
#     """
#     Handle a single request
# 
#     :param payload: Serialized PyledgerRequest message
#     :return:
#     """
#     handler = Handler()
#     message = PyledgerRequest()
#     response = PyledgerResponse()
# 
#     try:
#         message.ParseFromString(payload)
#     except DecodeError:
#         response.successful = False
#         response.data = b'Message not properly formatted'
#         return response.SerializeToString()
# 
#     if message.request not in handler_methods(handler):
#         response.successful = False
#         response.data = 'Request type {} not available'.format(message.request).encode()
#         return response.SerializeToString()
# 
#     else:
#         # Handle authentication
#         if message.request in permissions_registry:
#             user = User.from_name(message.user)
#             permission_required = permissions_registry[message.request]
# 
#             if not user.check_password(message.password):
#                 response.successful = False
#                 response.data = b'Wrong user and/or password'
#                 return response.SerializeToString()
# 
#             if user.get_permissions().value > permission_required.value:
#                 response.successful = False
#                 response.data = b'Not enough permissions'
#                 return response.SerializeToString()
# 
#             session = Session.from_key(message.session_key)
# 
#             if not session:
#                 response.successful = False
#                 response.data = b'Session not available'
#                 return response.SerializeToString()
# 
#             if not session.user == user:
#                 response.successful = False
#                 response.data = b'Session not owned by this user'
#                 return response.SerializeToString()
# 
#             if session.until < datetime.datetime.now():
#                 response.successful = False
#                 response.data = b'Session expired, restart your client'
#                 return response.SerializeToString()
# 
#         # Select the function from the handler
#         try:
#             print('Handling message', message)
#             successful, result = getattr(handler, message.request)(message)
#         except Exception as exc:
#             successful = False
#             result = b'Exception in user function: ' + repr(exc).encode('utf-8')
# 
#         response.successful = successful
#         response.data = result
#         return response.SerializeToString()
# 
# Path: pyledger/server/contract.py
# def register_contract(contract, description=''):
#     """
#     Register a contract and make it
#     :param contract:
#     :param description:
#     :return:
#     """
#     global contract_registry
# 
#     if contract.__class__.__name__ in contract_registry:
#         raise ValueError('A contract with the same name already registered')
#     else:
#         contract_registry[contract.__class__.__name__] = contract
# 
#     db_contract = Contract()
#     db_contract.name = contract.__class__.__name__
#     db_contract.created = datetime.datetime.now()
#     db_contract.description = description
# 
#     first_status = Status()
#     first_status.contract = db_contract
#     first_status.when = datetime.datetime.now()
#     first_status.attributes = status(contract).dump()
#     # Genesis key is the name of the contract
#     first_status.key = contract.__class__.__name__.encode('utf-8')
# 
#     DB.session.add(db_contract)
#     DB.session.add(first_status)
#     DB.session.commit()
# 
# class SimpleContract(BaseContract):
#     """
#     Contract that uses SimpleStatus for serialization.
# 
#     The goal of this class is to make a contact feel just like a Python class.
#     """
#     _status_class = SimpleStatus
# 
# Path: pyledger/server/db.py
# DB = Handler()
# 
# Path: pyledger/server/auth.py
# def create_master(password):
# def create_user(name, password):
# def allow(permission):
#     def decorator(func):
# def method_allow(permission):
#     def decorator(func):


from autobahn.asyncio.websocket import WebSocketServerProtocol, \
    WebSocketServerFactory
from pyledger.server.handlers import handle_request
from pyledger.server.contract import register_contract, SimpleContract
from pyledger.server.db import DB
from pyledger.server.auth import Permissions, method_allow
import asyncio

            self.accounts[key] = 0.0
            return key

        def increment(self, key: str, quantity: float):
            if key not in self.accounts:
                raise Exception('Account not found')

            self.accounts[key] += quantity

        def transfer(self, source: str, dest: str, quantity: float):
            if source not in self.accounts:
                raise Exception('Source account not found')
            if dest not in self.accounts:
                raise Exception('Destination account not found')
            if self.accounts[source] < quantity:
                raise Exception('Not enough funds in source account')
            if quantity < 0:
                raise Exception('You cannot transfer negative currency')

            self.accounts[source] -= quantity
            self.accounts[dest] += quantity

        def balance(self, key: str):
            if key not in self.accounts:
                print(self.accounts)
                raise Exception('Account not found')

            return str(self.accounts[key])


# Path: pyledger/server/handlers.py
# def handle_request(payload: bytes):
#     """
#     Handle a single request
# 
#     :param payload: Serialized PyledgerRequest message
#     :return:
#     """
#     handler = Handler()
#     message = PyledgerRequest()
#     response = PyledgerResponse()
# 
#     try:
#         message.ParseFromString(payload)
#     except DecodeError:
#         response.successful = False
#         response.data = b'Message not properly formatted'
#         return response.SerializeToString()
# 
#     if message.request not in handler_methods(handler):
#         response.successful = False
#         response.data = 'Request type {} not available'.format(message.request).encode()
#         return response.SerializeToString()
# 
#     else:
#         # Handle authentication
#         if message.request in permissions_registry:
#             user = User.from_name(message.user)
#             permission_required = permissions_registry[message.request]
# 
#             if not user.check_password(message.password):
#                 response.successful = False
#                 response.data = b'Wrong user and/or password'
#                 return response.SerializeToString()
# 
#             if user.get_permissions().value > permission_required.value:
#                 response.successful = False
#                 response.data = b'Not enough permissions'
#                 return response.SerializeToString()
# 
#             session = Session.from_key(message.session_key)
# 
#             if not session:
#                 response.successful = False
#                 response.data = b'Session not available'
#                 return response.SerializeToString()
# 
#             if not session.user == user:
#                 response.successful = False
#                 response.data = b'Session not owned by this user'
#                 return response.SerializeToString()
# 
#             if session.until < datetime.datetime.now():
#                 response.successful = False
#                 response.data = b'Session expired, restart your client'
#                 return response.SerializeToString()
# 
#         # Select the function from the handler
#         try:
#             print('Handling message', message)
#             successful, result = getattr(handler, message.request)(message)
#         except Exception as exc:
#             successful = False
#             result = b'Exception in user function: ' + repr(exc).encode('utf-8')
# 
#         response.successful = successful
#         response.data = result
#         return response.SerializeToString()
# 
# Path: pyledger/server/contract.py
# def register_contract(contract, description=''):
#     """
#     Register a contract and make it
#     :param contract:
#     :param description:
#     :return:
#     """
#     global contract_registry
# 
#     if contract.__class__.__name__ in contract_registry:
#         raise ValueError('A contract with the same name already registered')
#     else:
#         contract_registry[contract.__class__.__name__] = contract
# 
#     db_contract = Contract()
#     db_contract.name = contract.__class__.__name__
#     db_contract.created = datetime.datetime.now()
#     db_contract.description = description
# 
#     first_status = Status()
#     first_status.contract = db_contract
#     first_status.when = datetime.datetime.now()
#     first_status.attributes = status(contract).dump()
#     # Genesis key is the name of the contract
#     first_status.key = contract.__class__.__name__.encode('utf-8')
# 
#     DB.session.add(db_contract)
#     DB.session.add(first_status)
#     DB.session.commit()
# 
# class SimpleContract(BaseContract):
#     """
#     Contract that uses SimpleStatus for serialization.
# 
#     The goal of this class is to make a contact feel just like a Python class.
#     """
#     _status_class = SimpleStatus
# 
# Path: pyledger/server/db.py
# DB = Handler()
# 
# Path: pyledger/server/auth.py
# def create_master(password):
# def create_user(name, password):
# def allow(permission):
#     def decorator(func):
# def method_allow(permission):
#     def decorator(func):


# Path: pyledger/server/ws.py
from autobahn.asyncio.websocket import WebSocketServerProtocol, \
    WebSocketServerFactory
from pyledger.server.handlers import handle_request
from pyledger.server.contract import register_contract, SimpleContract
from pyledger.server.db import DB
from pyledger.server.auth import Permissions, method_allow
import asyncio


            self.accounts[key] = 0.0
            return key

        def increment(self, key: str, quantity: float):
            if key not in self.accounts:
                raise Exception('Account not found')

            self.accounts[key] += quantity

        def transfer(self, source: str, dest: str, quantity: float):
            if source not in self.accounts:
                raise Exception('Source account not found')
            if dest not in self.accounts:
                raise Exception('Destination account not found')
            if self.accounts[source] < quantity:
                raise Exception('Not enough funds in source account')
            if quantity < 0:
                raise Exception('You cannot transfer negative currency')

            self.accounts[source] -= quantity
            self.accounts[dest] += quantity

        def balance(self, key: str):
            if key not in self.accounts:
                print(self.accounts)
                raise Exception('Account not found')

            return str(self.accounts[key])


    register_contract(DigitalCurrency())