diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b36c295 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,51 @@ +# Changelog + +## [1.1.0] - 2024-12-13 + +### Added +- **XML Rate Methods**: Complete implementation of FixedFloat XML endpoints + - `get_rates_fixed_xml()` - Get fixed exchange rates without authentication + - `get_rates_float_xml()` - Get floating exchange rates without authentication + - `xml_req()` - Helper method for XML GET requests + - `parse_xml_rates()` - XML parser with error handling +- **Flexible Output**: Support for both parsed Python data and raw XML +- **Complete Documentation**: Updated README with XML methods examples and best practices +- **100% API Coverage**: All 9 FixedFloat API methods now implemented + +### Changed +- Version bumped to 1.1.0 +- Enhanced package description to mention XML rate methods +- Added comprehensive examples for XML methods usage + +### Technical Details +- No new dependencies (uses built-in `xml.etree.ElementTree`) +- XML methods don't require API authentication +- Perfect for mass operations with local caching (TTL 5-10 minutes) +- No rate limiting on XML endpoints +- Robust error handling for XML parsing and HTTP requests + +### Usage Examples +```python +# Get parsed exchange rates +api = FixedFloatApi(key=None, secret=None) +rates = api.get_rates_fixed_xml(parse=True) + +# Get raw XML for custom processing +raw_xml = api.get_rates_fixed_xml(parse=False) +``` + +### API Coverage +- ✅ POST /api/v2/ccies (ccies) +- ✅ POST /api/v2/price (price) +- ✅ POST /api/v2/create (create) +- ✅ POST /api/v2/order (order) +- ✅ POST /api/v2/emergency (emergency) +- ✅ POST /api/v2/setEmail (setEmail) +- ✅ POST /api/v2/qr (qr) +- ✅ GET /rates/fixed.xml (get_rates_fixed_xml) **NEW** +- ✅ GET /rates/float.xml (get_rates_float_xml) **NEW** + +## [1.0.3] - Previous Release +- Basic API methods implementation +- Authentication and request signing +- Error handling for API responses \ No newline at end of file diff --git a/README.md b/README.md index e764b12..df017ce 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,49 @@ response = api.custom_request(method, data) print(response) ``` +## XML Rate Methods (No Authentication Required) + +These methods don't require API keys and are perfect for mass operations with local caching: + +```python +from fixedfloatapi import FixedFloatApi + +# You can create an instance without API keys for XML methods +api = FixedFloatApi(key=None, secret=None) + +# Get fixed exchange rates (parsed as Python list) +fixed_rates = api.get_rates_fixed_xml(parse=True) +print(f"Found {len(fixed_rates)} fixed rate pairs") +for rate in fixed_rates[:3]: # Show first 3 rates + print(f"{rate['from']} -> {rate['to']}: {rate['out']} (min: {rate['minamount']})") + +# Get floating exchange rates (parsed as Python list) +float_rates = api.get_rates_float_xml(parse=True) +print(f"Found {len(float_rates)} floating rate pairs") + +# Get raw XML if you prefer to parse it yourself +raw_xml = api.get_rates_fixed_xml(parse=False) +print("Raw XML length:", len(raw_xml)) + +# Example rate data structure: +# { +# 'from': 'BTC', +# 'to': 'ETH', +# 'in': 1.0, +# 'out': 17.720391807658, +# 'amount': 191.11148571181, +# 'tofee': '0.0004967000 ETH', +# 'minamount': '0.0004896204 BTC', +# 'maxamount': '1.5160672800 BTC' +# } +``` + +**Recommended usage for XML methods:** +- Cache the results locally with TTL of 5-10 minutes +- Use for displaying available exchange pairs and rates +- Perfect for building rate comparison tools +- No rate limiting (unlimited requests) + For more information, see the [API documentation](https://fixedfloat.com/api) diff --git a/fixedfloatapi/FixedFloatAPI.py b/fixedfloatapi/FixedFloatAPI.py index 6065eaf..2c8b599 100644 --- a/fixedfloatapi/FixedFloatAPI.py +++ b/fixedfloatapi/FixedFloatAPI.py @@ -2,6 +2,7 @@ import hashlib import requests import hmac +import xml.etree.ElementTree as ET class FixedFloatApi: RESP_OK = 0 @@ -69,3 +70,108 @@ def qr(self, data): def custom_request(self, method, data): return self.req(method, data) + + def xml_req(self, endpoint): + """ + Make a GET request to XML endpoints (no authentication required) + + Args: + endpoint (str): The XML endpoint path (e.g., 'rates/fixed.xml') + + Returns: + str: Raw XML response content + + Raises: + Exception: If request fails or returns non-200 status + """ + url = f'https://ff.io/{endpoint}' + + response = requests.get(url, verify=True) + + if response.status_code != 200: + raise Exception(f'XML request failed with status {response.status_code}: {response.text}') + + return response.text + + def parse_xml_rates(self, xml_content): + """ + Parse XML rates content into Python data structure + + Args: + xml_content (str): Raw XML content + + Returns: + list: List of rate dictionaries with parsed data + + Raises: + Exception: If XML parsing fails + """ + try: + root = ET.fromstring(xml_content) + rates = [] + + for item in root.findall('item'): + rate_data = {} + for child in item: + if child.tag in ['in', 'out', 'amount']: + # Convert numeric fields to float + try: + rate_data[child.tag] = float(child.text) if child.text else 0.0 + except (ValueError, TypeError): + rate_data[child.tag] = 0.0 + else: + # Keep string fields as strings + rate_data[child.tag] = child.text if child.text else '' + + rates.append(rate_data) + + return rates + + except ET.ParseError as e: + raise Exception(f'Failed to parse XML: {e}') + + def get_rates_fixed_xml(self, parse=True): + """ + Get fixed exchange rates in XML format + + This method doesn't require authentication and provides all available + fixed exchange rates. Recommended for mass operations with local caching (TTL 5-10 minutes). + + Args: + parse (bool): If True, parse XML to Python dict. If False, return raw XML string. + + Returns: + list or str: Parsed rates data (if parse=True) or raw XML string (if parse=False) + + Raises: + Exception: If request fails or XML parsing fails (when parse=True) + """ + xml_content = self.xml_req('rates/fixed.xml') + + if parse: + return self.parse_xml_rates(xml_content) + else: + return xml_content + + def get_rates_float_xml(self, parse=True): + """ + Get floating exchange rates in XML format + + This method doesn't require authentication and provides all available + floating exchange rates. Recommended for mass operations with local caching (TTL 5-10 minutes). + + Args: + parse (bool): If True, parse XML to Python dict. If False, return raw XML string. + + Returns: + list or str: Parsed rates data (if parse=True) or raw XML string (if parse=False) + + Raises: + Exception: If request fails or XML parsing fails (when parse=True) + """ + xml_content = self.xml_req('rates/float.xml') + + if parse: + return self.parse_xml_rates(xml_content) + else: + return xml_content diff --git a/setup.py b/setup.py index cfd5da5..5cf3788 100644 --- a/setup.py +++ b/setup.py @@ -4,9 +4,9 @@ name='FixedFloatApi', packages=find_packages(), include_package_data=True, - version='1.0.3', + version='1.1.0', license='MIT', - description='Python wrapper for interacting with the FixedFloat API to exchange cryptocurrencies.', + description='Python wrapper for interacting with the FixedFloat API to exchange cryptocurrencies. Now includes XML rate methods for mass operations.', long_description=open('README.md').read(), long_description_content_type='text/markdown', author='JobiansTechie',