コード例 #1
0
ファイル: rest.py プロジェクト: robinsingh1/raiden
class RestAPI(object):
    """
    This wraps around the actual RaidenAPI in api/python.
    It will provide the additional, neccessary RESTful logic and
    the proper JSON-encoding of the Objects provided by the RaidenAPI
    """
    version = 1

    def __init__(self, raiden_api):
        self.raiden_api = raiden_api
        self.channel_schema = ChannelSchema()
        self.channel_list_schema = ChannelListSchema()
        self.tokens_list_schema = TokensListSchema()
        self.partner_per_token_list_schema = PartnersPerTokenListSchema()
        self.transfer_schema = TransferSchema()

    def open(self,
             partner_address,
             token_address,
             settle_timeout,
             balance=None):
        raiden_service_result = self.raiden_api.open(token_address,
                                                     partner_address,
                                                     settle_timeout)

        if balance:
            # make initial deposit
            raiden_service_result = self.raiden_api.deposit(
                token_address, partner_address, balance)

        result = self.channel_schema.dump(
            channel_to_api_dict(raiden_service_result))
        return jsonify(result.data)

    def deposit(self, token_address, partner_address, amount):

        raiden_service_result = self.raiden_api.deposit(
            token_address, partner_address, amount)

        result = self.channel_schema.dump(
            channel_to_api_dict(raiden_service_result))
        return jsonify(result.data)

    def close(self, token_address, partner_address):

        raiden_service_result = self.raiden_api.close(token_address,
                                                      partner_address)

        result = self.channel_schema.dump(
            channel_to_api_dict(raiden_service_result))
        return jsonify(result.data)

    def connect(self,
                token_address,
                funds,
                initial_channel_target=None,
                joinable_funds_target=None):

        self.raiden_api.connect_token_network(token_address, funds,
                                              initial_channel_target,
                                              joinable_funds_target)

    def leave(self, token_address, wait_for_settle=None, timeout=None):

        self.raiden_api.leave_token_network(token_address, wait_for_settle,
                                            timeout)

    def get_channel_list(self, token_address=None, partner_address=None):
        raiden_service_result = self.raiden_api.get_channel_list(
            token_address, partner_address)
        assert isinstance(raiden_service_result, list)

        channel_list = ChannelList(raiden_service_result)
        result = self.channel_list_schema.dump(channel_list)
        return jsonify(result.data)

    def get_tokens_list(self):
        raiden_service_result = self.raiden_api.get_tokens_list()
        assert isinstance(raiden_service_result, list)

        new_list = []
        for result in raiden_service_result:
            new_list.append({'address': result})

        tokens_list = TokensList(new_list)
        result = self.tokens_list_schema.dump(tokens_list)
        return jsonify(result.data)

    def get_network_events(self, from_block, to_block):
        raiden_service_result = self.raiden_api.get_network_events(
            from_block, to_block)
        return normalize_events_list(raiden_service_result)

    def get_token_network_events(self, token_address, from_block, to_block):
        raiden_service_result = self.raiden_api.get_token_network_events(
            token_address, from_block, to_block)
        return normalize_events_list(raiden_service_result)

    def get_channel_events(self, channel_address, from_block, to_block):
        raiden_service_result = self.raiden_api.get_channel_events(
            channel_address, from_block, to_block)
        return normalize_events_list(raiden_service_result)

    def get_channel(self, channel_address):
        channel = self.raiden_api.get_channel(channel_address)
        result = self.channel_schema.dump(channel_to_api_dict(channel))
        return jsonify(result.data)

    def get_partners_by_token(self, token_address):
        return_list = []
        raiden_service_result = self.raiden_api.get_channel_list(token_address)
        for result in raiden_service_result:
            return_list.append({
                'partner_address':
                result.partner_address,
                'channel':
                url_for(
                    # TODO: Somehow nicely parameterize this for future versions
                    'v1_resources.channelsresourcebychanneladdress',
                    channel_address=result.channel_address),
            })

        schema_list = PartnersPerTokenList(return_list)
        result = self.partner_per_token_list_schema.dump(schema_list)
        return jsonify(result.data)

    def initiate_transfer(self, token_address, target_address, amount,
                          identifier):

        if identifier is None:
            identifier = self.raiden_api.create_default_identifier(
                target_address, token_address)

        try:
            self.raiden_api.transfer(token_address=token_address,
                                     target=target_address,
                                     amount=amount,
                                     identifier=identifier)
        except (InvalidAmount, InvalidAddress, NoPathError) as e:
            return make_response(str(e), httplib.CONFLICT)

        transfer = {
            'initiator_address': self.raiden_api.raiden.address,
            'token_address': token_address,
            'target_address': target_address,
            'amount': amount,
            'identifier': identifier,
        }
        result = self.transfer_schema.dump(transfer)
        return jsonify(result.data)

    def patch_channel(self, channel_address, balance=None, state=None):
        if balance is not None and state is not None:
            return make_response(
                'Can not update balance and change channel state at the same time',
                httplib.CONFLICT,
            )
        elif balance is None and state is None:
            return make_response(
                'Nothing to do. Should either provide \'balance\' or \'state\' argument',
                httplib.BAD_REQUEST,
            )

        # find the channel
        channel = self.raiden_api.get_channel(channel_address)
        current_state = channel.state

        # if we patch with `balance` it's a deposit
        if balance is not None:
            if current_state != CHANNEL_STATE_OPENED:
                return make_response(
                    "Can't deposit on a closed channel",
                    httplib.CONFLICT,
                )
            raiden_service_result = self.raiden_api.deposit(
                channel.token_address, channel.partner_address, balance)
            result = self.channel_schema.dump(
                channel_to_api_dict(raiden_service_result))
            return jsonify(result.data)

        if state == CHANNEL_STATE_CLOSED:
            if current_state != CHANNEL_STATE_OPENED:
                return make_response(
                    httplib.CONFLICT,
                    'Attempted to close an already closed channel')
            raiden_service_result = self.raiden_api.close(
                channel.token_address, channel.partner_address)
            result = self.channel_schema.dump(
                channel_to_api_dict(raiden_service_result))
            return jsonify(result.data)

        if state == CHANNEL_STATE_SETTLED:
            if current_state == CHANNEL_STATE_SETTLED or current_state == CHANNEL_STATE_OPENED:
                return make_response(
                    'Attempted to settle a channel at its {} state'.format(
                        current_state),
                    httplib.CONFLICT,
                )
            raiden_service_result = self.raiden_api.settle(
                channel.token_address, channel.partner_address)
            result = self.channel_schema.dump(
                channel_to_api_dict(raiden_service_result))
            return jsonify(result.data)

        # should never happen, channel_state is validated in the schema
        return make_response(
            'Provided invalid channel state {}'.format(state),
            httplib.BAD_REQUEST,
        )

    def token_swap(self, target_address, identifier, role, sending_token,
                   sending_amount, receiving_token, receiving_amount):

        if role == 'maker':
            self.raiden_api.token_swap(
                from_token=sending_token,
                from_amount=sending_amount,
                to_token=receiving_token,
                to_amount=receiving_amount,
                target_address=target_address,
            )
        elif role == 'taker':
            self.raiden_api.expect_token_swap(
                identifier=identifier,
                from_token=sending_token,
                from_amount=sending_amount,
                to_token=receiving_token,
                to_amount=receiving_amount,
                target_address=target_address,
            )
        else:
            # should never happen, role is validated in the schema
            return make_response(
                'Provided invalid token swap role {}'.format(role),
                httplib.BAD_REQUEST,
            )
コード例 #2
0
class RestAPI(object):
    """
    This wraps around the actual RaidenAPI in api/python.
    It will provide the additional, neccessary RESTful logic and
    the proper JSON-encoding of the Objects provided by the RaidenAPI
    """
    version = 1

    def __init__(self, raiden_api):
        self.raiden_api = raiden_api
        self.channel_schema = ChannelSchema()
        self.channel_list_schema = ChannelListSchema()
        self.tokens_list_schema = TokensListSchema()
        self.partner_per_token_list_schema = PartnersPerTokenListSchema()
        self.transfer_schema = TransferSchema()

    def get_our_address(self):
        return {'our_address': address_encoder(self.raiden_api.address)}

    def register_token(self, token_address):
        manager_address = self.raiden_api.manager_address_if_token_registered(
            token_address)

        if manager_address is not None:
            return make_response('Token is already registered',
                                 httplib.CONFLICT)

        if manager_address is None:
            manager_address = self.raiden_api.register_token(token_address)

        return jsonify_with_response(data=dict(
            channel_manager_address=address_encoder(manager_address)),
                                     status_code=httplib.CREATED)

    def open(self,
             partner_address,
             token_address,
             settle_timeout=None,
             reveal_timeout=None,
             balance=None):
        try:
            raiden_service_result = self.raiden_api.open(
                token_address,
                partner_address,
                settle_timeout,
                reveal_timeout,
            )
        except (InvalidAddress, InvalidSettleTimeout, SamePeerAddress,
                AddressWithoutCode, NoTokenManager,
                DuplicatedChannelError) as e:
            return make_response(str(e), httplib.CONFLICT)

        if balance:
            # make initial deposit
            try:
                raiden_service_result = self.raiden_api.deposit(
                    token_address, partner_address, balance)
            except EthNodeCommunicationError as e:
                return make_response(str(e), httplib.REQUEST_TIMEOUT)
            except InsufficientFunds as e:
                return make_response(str(e), httplib.PAYMENT_REQUIRED)

        result = self.channel_schema.dump(
            channel_to_api_dict(raiden_service_result))
        return jsonify_with_response(data=result.data,
                                     status_code=httplib.CREATED)

    def deposit(self, token_address, partner_address, amount):
        try:
            raiden_service_result = self.raiden_api.deposit(
                token_address, partner_address, amount)
        except EthNodeCommunicationError as e:
            return make_response(str(e), httplib.REQUEST_TIMEOUT)
        except InsufficientFunds as e:
            return make_response(str(e), httplib.PAYMENT_REQUIRED)

        result = self.channel_schema.dump(
            channel_to_api_dict(raiden_service_result))
        return jsonify(result.data)

    def close(self, token_address, partner_address):

        raiden_service_result = self.raiden_api.close(token_address,
                                                      partner_address)

        result = self.channel_schema.dump(
            channel_to_api_dict(raiden_service_result))
        return jsonify(result.data)

    def connect(self,
                token_address,
                funds,
                initial_channel_target=None,
                joinable_funds_target=None):

        self.raiden_api.connect_token_network(token_address, funds,
                                              initial_channel_target,
                                              joinable_funds_target)
        return make_response('', httplib.NO_CONTENT)

    def leave(self, token_address):
        self.raiden_api.leave_token_network(token_address)
        return make_response('', httplib.NO_CONTENT)

    def get_connection_manager_funds(self, token_address):
        connection_manager = self.raiden_api.get_connection_manager_funds(
            token_address)

        if connection_manager is None:
            return make_response('No connection manager exists for token',
                                 httplib.NO_CONTENT)

        if connection_manager is not None:
            return jsonify(connection_manager)

    def get_connection_managers_list(self):
        raiden_service_result = self.raiden_api.get_connection_managers_list()
        assert isinstance(raiden_service_result, list)

        new_list = []
        for result in raiden_service_result:
            new_list.append(address_encoder(result))

        return jsonify(new_list)

    def get_channel_list(self, token_address=None, partner_address=None):
        raiden_service_result = self.raiden_api.get_channel_list(
            token_address, partner_address)
        assert isinstance(raiden_service_result, list)

        channel_list = ChannelList(raiden_service_result)
        result = self.channel_list_schema.dump(channel_list)
        return jsonify(result.data)

    def get_tokens_list(self):
        raiden_service_result = self.raiden_api.get_tokens_list()
        assert isinstance(raiden_service_result, list)

        new_list = []
        for result in raiden_service_result:
            new_list.append({'address': result})

        tokens_list = TokensList(new_list)
        result = self.tokens_list_schema.dump(tokens_list)
        return jsonify(result.data)

    def get_network_events(self, from_block, to_block):
        raiden_service_result = self.raiden_api.get_network_events(
            from_block, to_block)
        return normalize_events_list(raiden_service_result)

    def get_token_network_events(self, token_address, from_block, to_block):
        raiden_service_result = self.raiden_api.get_token_network_events(
            token_address, from_block, to_block)
        return normalize_events_list(raiden_service_result)

    def get_channel_events(self, channel_address, from_block, to_block):
        raiden_service_result = self.raiden_api.get_channel_events(
            channel_address, from_block, to_block)
        return normalize_events_list(raiden_service_result)

    def get_channel(self, channel_address):
        channel = self.raiden_api.get_channel(channel_address)
        result = self.channel_schema.dump(channel_to_api_dict(channel))
        return jsonify(result.data)

    def get_partners_by_token(self, token_address):
        return_list = []
        raiden_service_result = self.raiden_api.get_channel_list(token_address)
        for result in raiden_service_result:
            return_list.append({
                'partner_address':
                result.partner_address,
                'channel':
                url_for(
                    # TODO: Somehow nicely parameterize this for future versions
                    'v1_resources.channelsresourcebychanneladdress',
                    channel_address=result.channel_address),
            })

        schema_list = PartnersPerTokenList(return_list)
        result = self.partner_per_token_list_schema.dump(schema_list)
        return jsonify(result.data)

    def initiate_transfer(self, token_address, target_address, amount,
                          identifier):

        if identifier is None:
            identifier = create_default_identifier()

        try:
            transfer_result = self.raiden_api.transfer(
                token_address=token_address,
                target=target_address,
                amount=amount,
                identifier=identifier)
        except (InvalidAmount, InvalidAddress, NoPathError) as e:
            return make_response(str(e), httplib.CONFLICT)
        except (InsufficientFunds) as e:
            return make_response(str(e), httplib.PAYMENT_REQUIRED)

        if transfer_result is False:
            return make_response(
                "Payment couldn't be completed "
                "(insufficient funds or no route to target).",
                httplib.CONFLICT)

        transfer = {
            'initiator_address': self.raiden_api.raiden.address,
            'token_address': token_address,
            'target_address': target_address,
            'amount': amount,
            'identifier': identifier,
        }
        result = self.transfer_schema.dump(transfer)
        return jsonify(result.data)

    def patch_channel(self, channel_address, balance=None, state=None):
        if balance is not None and state is not None:
            return make_response(
                'Can not update balance and change channel state at the same time',
                httplib.CONFLICT,
            )
        elif balance is None and state is None:
            return make_response(
                'Nothing to do. Should either provide \'balance\' or \'state\' argument',
                httplib.BAD_REQUEST,
            )

        # find the channel
        try:
            channel = self.raiden_api.get_channel(channel_address)
        except ChannelNotFound:
            return make_response(
                "Requested channel {} not found".format(
                    address_encoder(channel_address)), httplib.CONFLICT)

        current_state = channel.state

        # if we patch with `balance` it's a deposit
        if balance is not None:
            if current_state != CHANNEL_STATE_OPENED:
                return make_response(
                    "Can't deposit on a closed channel",
                    httplib.CONFLICT,
                )
            try:
                raiden_service_result = self.raiden_api.deposit(
                    channel.token_address, channel.partner_address, balance)
            except InsufficientFunds as e:
                return make_response(str(e), httplib.PAYMENT_REQUIRED)
            result = self.channel_schema.dump(
                channel_to_api_dict(raiden_service_result))
            return jsonify(result.data)

        if state == CHANNEL_STATE_CLOSED:
            if current_state != CHANNEL_STATE_OPENED:
                return make_response(
                    'Attempted to close an already closed channel',
                    httplib.CONFLICT,
                )
            raiden_service_result = self.raiden_api.close(
                channel.token_address, channel.partner_address)
            result = self.channel_schema.dump(
                channel_to_api_dict(raiden_service_result))
            return jsonify(result.data)

        if state == CHANNEL_STATE_SETTLED:
            if current_state == CHANNEL_STATE_SETTLED or current_state == CHANNEL_STATE_OPENED:
                return make_response(
                    'Attempted to settle a channel at its {} state'.format(
                        current_state),
                    httplib.CONFLICT,
                )
            try:
                raiden_service_result = self.raiden_api.settle(
                    channel.token_address, channel.partner_address)
            except InvalidState:
                result = make_response(
                    'Settlement period is not yet over',
                    httplib.CONFLICT,
                )
            else:
                result = self.channel_schema.dump(
                    channel_to_api_dict(raiden_service_result))
            return jsonify(result.data)

        # should never happen, channel_state is validated in the schema
        return make_response(
            'Provided invalid channel state {}'.format(state),
            httplib.BAD_REQUEST,
        )

    def token_swap(self, target_address, identifier, role, sending_token,
                   sending_amount, receiving_token, receiving_amount):

        if role == 'maker':
            self.raiden_api.token_swap(
                identifier=identifier,
                maker_token=sending_token,
                maker_amount=sending_amount,
                maker_address=self.raiden_api.address,
                taker_token=receiving_token,
                taker_amount=receiving_amount,
                taker_address=target_address,
            )
        elif role == 'taker':
            self.raiden_api.expect_token_swap(
                identifier=identifier,
                maker_token=receiving_token,
                maker_amount=receiving_amount,
                maker_address=target_address,
                taker_token=sending_token,
                taker_amount=sending_amount,
                taker_address=self.raiden_api.address)
        else:
            # should never happen, role is validated in the schema
            return make_response(
                'Provided invalid token swap role {}'.format(role),
                httplib.BAD_REQUEST,
            )

        return jsonify_with_response(dict(), httplib.CREATED)