"""
Binance Wallet REST API

OpenAPI Specification for the Binance Wallet REST API
The version of the OpenAPI document: 1.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)

Do not edit the class manually.
"""

import json
import pytest
import requests

from unittest.mock import MagicMock, patch
from urllib.parse import parse_qs

from binance_common.configuration import ConfigurationRestAPI
from binance_common.errors import RequiredError
from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel

from binance_sdk_wallet.rest_api.api import CapitalApi
from binance_sdk_wallet.rest_api.models import AllCoinsInformationResponse
from binance_sdk_wallet.rest_api.models import DepositAddressResponse
from binance_sdk_wallet.rest_api.models import DepositHistoryResponse
from binance_sdk_wallet.rest_api.models import (
    FetchDepositAddressListWithNetworkResponse,
)
from binance_sdk_wallet.rest_api.models import FetchWithdrawAddressListResponse
from binance_sdk_wallet.rest_api.models import FetchWithdrawQuotaResponse
from binance_sdk_wallet.rest_api.models import OneClickArrivalDepositApplyResponse
from binance_sdk_wallet.rest_api.models import WithdrawResponse
from binance_sdk_wallet.rest_api.models import WithdrawHistoryResponse


class TestCapitalApi:
    @pytest.fixture(autouse=True)
    def setup_client(self):
        """Setup a client instance with mocked session before each test method."""
        self.mock_session = MagicMock(spec=requests.Session)
        config = ConfigurationRestAPI(
            api_key="test-api-key",
            api_secret="test-api-secret",
        )
        self.client = CapitalApi(configuration=config, session=self.mock_session)

    def set_mock_response(self, data: dict = {}, status_code=200, headers=None):
        """Helper method to setup mock response for the client's session request."""
        if headers is None:
            headers = {}

        mock_response = MagicMock()
        mock_response.status_code = status_code
        mock_response.json.return_value = data
        mock_response.text = json.dumps(data)
        mock_response.headers = headers

        self.mock_session.request.return_value = mock_response

    @patch("binance_common.utils.get_signature")
    def test_all_coins_information_success(self, mock_get_signature):
        """Test all_coins_information() successfully with required parameters only."""

        expected_response = [
            {
                "coin": "1MBABYDOGE",
                "depositAllEnable": True,
                "withdrawAllEnable": True,
                "name": "1M x BABYDOGE",
                "free": "34941.1",
                "locked": "0",
                "freeze": "0",
                "withdrawing": "0",
                "ipoing": "0",
                "ipoable": "0",
                "storage": "0",
                "isLegalMoney": False,
                "trading": True,
                "networkList": [
                    {
                        "network": "BSC",
                        "coin": "1MBABYDOGE",
                        "withdrawIntegerMultiple": "0.01",
                        "isDefault": False,
                        "depositEnable": True,
                        "withdrawEnable": True,
                        "depositDesc": "",
                        "withdrawDesc": "",
                        "specialTips": "",
                        "specialWithdrawTips": "",
                        "name": "BNB Smart Chain (BEP20)",
                        "resetAddressStatus": False,
                        "addressRegex": "^(0x)[0-9A-Fa-f]{40}$",
                        "memoRegex": "",
                        "withdrawFee": "10",
                        "withdrawMin": "20",
                        "withdrawMax": "9999999999",
                        "withdrawInternalMin": "0.01",
                        "depositDust": "0.01",
                        "minConfirm": 5,
                        "unLockConfirm": 0,
                        "sameAddress": False,
                        "withdrawTag": False,
                        "estimatedArrivalTime": 1,
                        "busy": False,
                        "contractAddressUrl": "https://bscscan.com/token/",
                        "contractAddress": "0xc748673057861a797275cd8a068abb95a902e8de",
                        "denomination": 1000000,
                    },
                    {
                        "network": "ETH",
                        "coin": "1MBABYDOGE",
                        "withdrawIntegerMultiple": "0.01",
                        "isDefault": True,
                        "depositEnable": True,
                        "withdrawEnable": True,
                        "depositDesc": "",
                        "withdrawDesc": "",
                        "specialTips": "",
                        "specialWithdrawTips": "",
                        "name": "Ethereum (ERC20)",
                        "resetAddressStatus": False,
                        "addressRegex": "^(0x)[0-9A-Fa-f]{40}$",
                        "memoRegex": "",
                        "withdrawFee": "1511",
                        "withdrawMin": "3022",
                        "withdrawMax": "9999999999",
                        "withdrawInternalMin": "0.01",
                        "depositDust": "0.01",
                        "minConfirm": 6,
                        "unLockConfirm": 64,
                        "sameAddress": False,
                        "withdrawTag": False,
                        "estimatedArrivalTime": 2,
                        "busy": False,
                        "contractAddressUrl": "https://etherscan.io/address/",
                        "contractAddress": "0xac57de9c1a09fec648e93eb98875b212db0d460b",
                        "denomination": 1000000,
                    },
                ],
            }
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.all_coins_information()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/config/getall" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(AllCoinsInformationResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif is_oneof or is_list or hasattr(AllCoinsInformationResponse, "from_dict"):
            expected = AllCoinsInformationResponse.from_dict(expected_response)
        else:
            expected = AllCoinsInformationResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_all_coins_information_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test all_coins_information() successfully with optional parameters."""

        params = {"recv_window": 5000}

        expected_response = [
            {
                "coin": "1MBABYDOGE",
                "depositAllEnable": True,
                "withdrawAllEnable": True,
                "name": "1M x BABYDOGE",
                "free": "34941.1",
                "locked": "0",
                "freeze": "0",
                "withdrawing": "0",
                "ipoing": "0",
                "ipoable": "0",
                "storage": "0",
                "isLegalMoney": False,
                "trading": True,
                "networkList": [
                    {
                        "network": "BSC",
                        "coin": "1MBABYDOGE",
                        "withdrawIntegerMultiple": "0.01",
                        "isDefault": False,
                        "depositEnable": True,
                        "withdrawEnable": True,
                        "depositDesc": "",
                        "withdrawDesc": "",
                        "specialTips": "",
                        "specialWithdrawTips": "",
                        "name": "BNB Smart Chain (BEP20)",
                        "resetAddressStatus": False,
                        "addressRegex": "^(0x)[0-9A-Fa-f]{40}$",
                        "memoRegex": "",
                        "withdrawFee": "10",
                        "withdrawMin": "20",
                        "withdrawMax": "9999999999",
                        "withdrawInternalMin": "0.01",
                        "depositDust": "0.01",
                        "minConfirm": 5,
                        "unLockConfirm": 0,
                        "sameAddress": False,
                        "withdrawTag": False,
                        "estimatedArrivalTime": 1,
                        "busy": False,
                        "contractAddressUrl": "https://bscscan.com/token/",
                        "contractAddress": "0xc748673057861a797275cd8a068abb95a902e8de",
                        "denomination": 1000000,
                    },
                    {
                        "network": "ETH",
                        "coin": "1MBABYDOGE",
                        "withdrawIntegerMultiple": "0.01",
                        "isDefault": True,
                        "depositEnable": True,
                        "withdrawEnable": True,
                        "depositDesc": "",
                        "withdrawDesc": "",
                        "specialTips": "",
                        "specialWithdrawTips": "",
                        "name": "Ethereum (ERC20)",
                        "resetAddressStatus": False,
                        "addressRegex": "^(0x)[0-9A-Fa-f]{40}$",
                        "memoRegex": "",
                        "withdrawFee": "1511",
                        "withdrawMin": "3022",
                        "withdrawMax": "9999999999",
                        "withdrawInternalMin": "0.01",
                        "depositDust": "0.01",
                        "minConfirm": 6,
                        "unLockConfirm": 64,
                        "sameAddress": False,
                        "withdrawTag": False,
                        "estimatedArrivalTime": 2,
                        "busy": False,
                        "contractAddressUrl": "https://etherscan.io/address/",
                        "contractAddress": "0xac57de9c1a09fec648e93eb98875b212db0d460b",
                        "denomination": 1000000,
                    },
                ],
            }
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.all_coins_information(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/config/getall" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(AllCoinsInformationResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif is_oneof or is_list or hasattr(AllCoinsInformationResponse, "from_dict"):
            expected = AllCoinsInformationResponse.from_dict(expected_response)
        else:
            expected = AllCoinsInformationResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_all_coins_information_server_error(self):
        """Test that all_coins_information() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.all_coins_information = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            self.client.all_coins_information()

    @patch("binance_common.utils.get_signature")
    def test_deposit_address_success(self, mock_get_signature):
        """Test deposit_address() successfully with required parameters only."""

        params = {
            "coin": "coin_example",
        }

        expected_response = {
            "address": "1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv",
            "coin": "BTC",
            "tag": "",
            "url": "https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv",
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.deposit_address(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/deposit/address" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"
        assert normalized["coin"] == "coin_example"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(DepositAddressResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif is_oneof or is_list or hasattr(DepositAddressResponse, "from_dict"):
            expected = DepositAddressResponse.from_dict(expected_response)
        else:
            expected = DepositAddressResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_deposit_address_success_with_optional_params(self, mock_get_signature):
        """Test deposit_address() successfully with optional parameters."""

        params = {
            "coin": "coin_example",
            "network": "network_example",
            "amount": 1.0,
            "recv_window": 5000,
        }

        expected_response = {
            "address": "1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv",
            "coin": "BTC",
            "tag": "",
            "url": "https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv",
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.deposit_address(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/deposit/address" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(DepositAddressResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif is_oneof or is_list or hasattr(DepositAddressResponse, "from_dict"):
            expected = DepositAddressResponse.from_dict(expected_response)
        else:
            expected = DepositAddressResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_deposit_address_missing_required_param_coin(self):
        """Test that deposit_address() raises RequiredError when 'coin' is missing."""
        params = {
            "coin": "coin_example",
        }
        params["coin"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'coin'"):
            self.client.deposit_address(**params)

    def test_deposit_address_server_error(self):
        """Test that deposit_address() raises an error when the server returns an error."""

        params = {
            "coin": "coin_example",
        }

        mock_error = Exception("ResponseError")
        self.client.deposit_address = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            self.client.deposit_address(**params)

    @patch("binance_common.utils.get_signature")
    def test_deposit_history_success(self, mock_get_signature):
        """Test deposit_history() successfully with required parameters only."""

        expected_response = [
            {
                "id": "769800519366885376",
                "amount": "0.001",
                "coin": "BNB",
                "network": "BNB",
                "status": 1,
                "address": "bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23",
                "addressTag": "101764890",
                "txId": "98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC",
                "insertTime": 1661493146000,
                "completeTime": 1661493146000,
                "transferType": 0,
                "confirmTimes": "1/1",
                "unlockConfirm": 0,
                "walletType": 0,
                "travelRuleStatus": 0,
            },
            {
                "id": "769754833590042625",
                "amount": "0.50000000",
                "coin": "IOTA",
                "network": "IOTA",
                "status": 1,
                "address": "SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW",
                "addressTag": "",
                "txId": "ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999",
                "insertTime": 1599620082000,
                "completeTime": 1661493146000,
                "transferType": 0,
                "confirmTimes": "1/1",
                "unlockConfirm": 0,
                "walletType": 0,
                "travelRuleStatus": 1,
            },
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.deposit_history()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/deposit/hisrec" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(DepositHistoryResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif is_oneof or is_list or hasattr(DepositHistoryResponse, "from_dict"):
            expected = DepositHistoryResponse.from_dict(expected_response)
        else:
            expected = DepositHistoryResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_deposit_history_success_with_optional_params(self, mock_get_signature):
        """Test deposit_history() successfully with optional parameters."""

        params = {
            "include_source": False,
            "coin": "coin_example",
            "status": 56,
            "start_time": 1623319461670,
            "end_time": 1641782889000,
            "offset": 0,
            "limit": 7,
            "recv_window": 5000,
            "tx_id": "1",
        }

        expected_response = [
            {
                "id": "769800519366885376",
                "amount": "0.001",
                "coin": "BNB",
                "network": "BNB",
                "status": 1,
                "address": "bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23",
                "addressTag": "101764890",
                "txId": "98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC",
                "insertTime": 1661493146000,
                "completeTime": 1661493146000,
                "transferType": 0,
                "confirmTimes": "1/1",
                "unlockConfirm": 0,
                "walletType": 0,
                "travelRuleStatus": 0,
            },
            {
                "id": "769754833590042625",
                "amount": "0.50000000",
                "coin": "IOTA",
                "network": "IOTA",
                "status": 1,
                "address": "SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW",
                "addressTag": "",
                "txId": "ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999",
                "insertTime": 1599620082000,
                "completeTime": 1661493146000,
                "transferType": 0,
                "confirmTimes": "1/1",
                "unlockConfirm": 0,
                "walletType": 0,
                "travelRuleStatus": 1,
            },
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.deposit_history(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/deposit/hisrec" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(DepositHistoryResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif is_oneof or is_list or hasattr(DepositHistoryResponse, "from_dict"):
            expected = DepositHistoryResponse.from_dict(expected_response)
        else:
            expected = DepositHistoryResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_deposit_history_server_error(self):
        """Test that deposit_history() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.deposit_history = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            self.client.deposit_history()

    @patch("binance_common.utils.get_signature")
    def test_fetch_deposit_address_list_with_network_success(self, mock_get_signature):
        """Test fetch_deposit_address_list_with_network() successfully with required parameters only."""

        params = {
            "coin": "coin_example",
        }

        expected_response = [
            {
                "coin": "ETH",
                "address": "0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4",
                "tag": "",
                "isDefault": 0,
            },
            {
                "coin": "ETH",
                "address": "0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4",
                "tag": "",
                "isDefault": 0,
            },
            {
                "coin": "ETH",
                "address": "0x00003ada75e7da97ba0db2fcde72131f712455e2",
                "tag": "",
                "isDefault": 1,
            },
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.fetch_deposit_address_list_with_network(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/deposit/address/list" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"
        assert normalized["coin"] == "coin_example"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(FetchDepositAddressListWithNetworkResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(FetchDepositAddressListWithNetworkResponse, "from_dict")
        ):
            expected = FetchDepositAddressListWithNetworkResponse.from_dict(
                expected_response
            )
        else:
            expected = FetchDepositAddressListWithNetworkResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_fetch_deposit_address_list_with_network_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test fetch_deposit_address_list_with_network() successfully with optional parameters."""

        params = {"coin": "coin_example", "network": "network_example"}

        expected_response = [
            {
                "coin": "ETH",
                "address": "0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4",
                "tag": "",
                "isDefault": 0,
            },
            {
                "coin": "ETH",
                "address": "0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4",
                "tag": "",
                "isDefault": 0,
            },
            {
                "coin": "ETH",
                "address": "0x00003ada75e7da97ba0db2fcde72131f712455e2",
                "tag": "",
                "isDefault": 1,
            },
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.fetch_deposit_address_list_with_network(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/deposit/address/list" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(FetchDepositAddressListWithNetworkResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(FetchDepositAddressListWithNetworkResponse, "from_dict")
        ):
            expected = FetchDepositAddressListWithNetworkResponse.from_dict(
                expected_response
            )
        else:
            expected = FetchDepositAddressListWithNetworkResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_fetch_deposit_address_list_with_network_missing_required_param_coin(self):
        """Test that fetch_deposit_address_list_with_network() raises RequiredError when 'coin' is missing."""
        params = {
            "coin": "coin_example",
        }
        params["coin"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'coin'"):
            self.client.fetch_deposit_address_list_with_network(**params)

    def test_fetch_deposit_address_list_with_network_server_error(self):
        """Test that fetch_deposit_address_list_with_network() raises an error when the server returns an error."""

        params = {
            "coin": "coin_example",
        }

        mock_error = Exception("ResponseError")
        self.client.fetch_deposit_address_list_with_network = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.fetch_deposit_address_list_with_network(**params)

    @patch("binance_common.utils.get_signature")
    def test_fetch_withdraw_address_list_success(self, mock_get_signature):
        """Test fetch_withdraw_address_list() successfully with required parameters only."""

        expected_response = [
            {
                "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
                "addressTag": "",
                "coin": "BTC",
                "name": "Satoshi",
                "network": "BTC",
                "origin": "bla",
                "originType": "others",
                "whiteStatus": True,
            }
        ]
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.fetch_withdraw_address_list()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/capital/withdraw/address/list" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(FetchWithdrawAddressListResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(FetchWithdrawAddressListResponse, "from_dict")
        ):
            expected = FetchWithdrawAddressListResponse.from_dict(expected_response)
        else:
            expected = FetchWithdrawAddressListResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_fetch_withdraw_address_list_server_error(self):
        """Test that fetch_withdraw_address_list() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.fetch_withdraw_address_list = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            self.client.fetch_withdraw_address_list()

    @patch("binance_common.utils.get_signature")
    def test_fetch_withdraw_quota_success(self, mock_get_signature):
