def _parse_post(req_class: T) -> T: json = request.get_json() if not json: raise exceptions.ApiException("JSON payload expected") try: return req_class.Schema().load(json) # type: ignore except marshmallow.ValidationError as ex: raise exceptions.InvalidRequest(**ex.messages)
def _parse_post(req_class: T) -> T: json = request.get_json() if not json: raise exceptions.ApiException("JSON payload expected") req, errors = req_class.Schema().load(json) # type: ignore if errors: raise exceptions.InvalidRequest(**errors) return req
def process_payment(iou_dict: dict, pathfinding_service: PathfindingService): if pathfinding_service.service_fee == 0: return if iou_dict is None: raise exceptions.MissingIOU # Basic IOU validity checks iou, errors = IOU.Schema().load(iou_dict) if errors: raise exceptions.InvalidRequest(**errors) if iou.receiver != pathfinding_service.address: raise exceptions.WrongIOURecipient( expected=pathfinding_service.address) if not iou.is_signature_valid(): raise exceptions.InvalidSignature # Compare with known IOU active_iou = pathfinding_service.database.get_iou( sender=iou.sender, claimed=False, ) if active_iou: if active_iou.expiration_block != iou.expiration_block: raise exceptions.UseThisIOU(iou=active_iou) expected_amount = active_iou.amount + pathfinding_service.service_fee else: claimed_iou = pathfinding_service.database.get_iou( sender=iou.sender, expiration_block=iou.expiration_block, claimed=True, ) if claimed_iou: raise exceptions.IOUAlreadyClaimed min_expiry = pathfinding_service.web3.eth.blockNumber + MIN_IOU_EXPIRY if iou.expiration_block < min_expiry: raise exceptions.IOUExpiredTooEarly(min_expiry=min_expiry) expected_amount = pathfinding_service.service_fee if iou.amount < expected_amount: raise exceptions.InsufficientServicePayment( expected_amount=expected_amount) # Check client's deposit in UserDeposit contract udc = pathfinding_service.user_deposit_contract udc_balance = udc.functions.effectiveBalance(iou.sender).call() required_deposit = round(expected_amount * UDC_SECURITY_MARGIN_FACTOR) if udc_balance < required_deposit: raise exceptions.DepositTooLow(required_deposit=required_deposit) # Save latest IOU iou.claimed = False pathfinding_service.database.upsert_iou(iou)
def post(self, token_network_address: str) -> Tuple[dict, int]: token_network_error = self._validate_token_network_argument( token_network_address) if token_network_error is not None: return token_network_error json = request.get_json() if not json: raise exceptions.ApiException('JSON payload expected') path_req, errors = PathRequest.Schema().load(json) if errors: raise exceptions.InvalidRequest(**errors) process_payment(path_req.iou, self.pathfinding_service) token_network = self.pathfinding_service.token_networks.get( TokenNetworkAddress(token_network_address)) # Existence is checked in _validate_token_network_argument assert token_network, 'Requested token network cannot be found' try: # only optional args if not None, so we can use defaults optional_args = {} for arg in ['diversity_penalty', 'fee_penalty']: value = getattr(path_req, arg) if value is not None: optional_args[arg] = value paths = token_network.get_paths( source=path_req.from_, target=path_req.to, value=path_req.value, max_paths=path_req.max_paths, **optional_args, ) except (NetworkXNoPath, NodeNotFound): return ( { 'errors': 'No suitable path found for transfer from {} to {}.'. format(path_req.from_, path_req.to) }, 400, ) return {'result': paths}, 200
def get(self, token_network_address: TokenNetworkAddress) -> Tuple[dict, int]: iou_request, errors = IOURequest.Schema().load(request.args) if errors: raise exceptions.InvalidRequest(**errors) if not iou_request.is_signature_valid(): raise exceptions.InvalidSignature if iou_request.timestamp < datetime.utcnow() - MAX_AGE_OF_IOU_REQUESTS: raise exceptions.RequestOutdated last_iou = self.pathfinding_service.database.get_iou( sender=iou_request.sender, claimed=False) if last_iou: last_iou = IOU.Schema(strict=True, exclude=["claimed"]).dump(last_iou)[0] return {"last_iou": last_iou}, 200 return {"last_iou": None}, 404
def get( self, token_network_address: str # pylint: disable=unused-argument ) -> Tuple[dict, int]: try: iou_request = IOURequest.Schema().load(request.args) except marshmallow.ValidationError as ex: raise exceptions.InvalidRequest(**ex.messages) if not iou_request.is_signature_valid(): raise exceptions.InvalidSignature if iou_request.timestamp < datetime.utcnow() - MAX_AGE_OF_IOU_REQUESTS: raise exceptions.RequestOutdated last_iou = self.pathfinding_service.database.get_iou( sender=iou_request.sender, claimed=False) if last_iou: last_iou = IOU.Schema(exclude=["claimed"]).dump(last_iou) return {"last_iou": last_iou}, 200 return {"last_iou": None}, 404