Lightweight, provider-agnostic currency conversion library for Python
Project description
converte_wallet
Статус: в разработке — API ядра активно пишется, интерфейсы ещё могут меняться.
Лёгкая Python-библиотека для конвертации валют. Работает из коробки — без регистрации и API-ключей. Поддерживает 150+ валют включая криптовалюты.
from app import Converter
c = Converter()
print(c.convert(1, "RUB", "BTC")) # 1 рубль в биткоин
print(c.convert(100, "USD", "EUR")) # 100 долларов в евро
print(c.convert(0.5, "ETH", "RUB")) # 0.5 эфира в рубли
Содержание
- Установка
- Быстрый старт
- Все методы Converter
- Провайдеры курсов
- Объект ConversionResult
- Кэширование
- CLI — командная строка
- Использование в проектах
- Разработка и тесты
- Структура проекта
Установка
Клонировать репозиторий
git clone https://github.com/your-username/converte_wallet.git
cd converte_wallet
Установить зависимости
pip install requests
Или через файл зависимостей:
pip install -r requirements
Установить как пакет (для импорта из других проектов)
pip install -e .
После этого в любом Python-файле на этой машине можно писать:
from converte_wallet import Converter
Без
pip install -e .импорт работает только из корня репозитория какfrom app import Converter.
Быстрый старт
Одна конвертация
from app import Converter
c = Converter() # по умолчанию — бесплатный провайдер, не нужен ключ
result = c.convert(100, "USD", "EUR")
print(result.amount) # 85.75 — сколько EUR получилось
print(result.rate) # 0.8575 — курс 1 USD = ? EUR
print(result.from_currency) # USD
print(result.to_currency) # EUR
print(result.provider) # currency-api
print(result) # красивый вывод одной строкой
Рубль в биткоин
from app import Converter
c = Converter()
result = c.convert(1, "RUB", "BTC")
print(result)
# 0.00000018 BTC (1 RUB = 1.79e-07 BTC, via currency-api)
Криптовалюта в фиат
result = c.convert(1, "BTC", "RUB")
print(result)
# 5586205.94 RUB (1 BTC = 5586205 RUB, via currency-api)
result = c.convert(2, "ETH", "USD")
print(result)
# 4364.94 USD (1 ETH = 2182.47 USD, via currency-api)
Пакетная конвертация нескольких пар сразу
from app import Converter
c = Converter()
results = c.convert_many([
(100, "USD", "EUR"),
(1, "RUB", "BTC"),
(0.5, "ETH", "USD"),
(1000, "JPY", "CNY"),
])
for r in results:
print(r)
Только курс без конвертации
rate = c.get_rate("USD", "RUB")
print(f"1 USD = {rate} RUB")
Все методы Converter
Converter(provider=None, cache_ttl=3600)
Создать конвертер.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
provider |
BaseProvider |
CurrencyAPIProvider() |
Провайдер курсов |
cache_ttl |
int |
3600 |
Время жизни кэша в секундах. 0 — без кэша |
from app import Converter
from app.providers import CoinGeckoProvider, FrankfurterProvider
# по умолчанию — CurrencyAPIProvider, 150+ валют, бесплатно
c = Converter()
# конкретный провайдер
c = Converter(provider=CoinGeckoProvider())
# кэш на 10 минут
c = Converter(cache_ttl=600)
# без кэша (каждый раз свежий запрос)
c = Converter(cache_ttl=0)
convert(amount, from_currency, to_currency) → ConversionResult
Конвертировать сумму.
result = c.convert(1000, "RUB", "USD")
result = c.convert(0.01, "BTC", "EUR")
result = c.convert(1, "rub", "btc") # регистр не важен
convert_many(conversions) → List[ConversionResult]
Конвертировать несколько пар за один вызов.
results = c.convert_many([
(100, "USD", "EUR"),
(1, "BTC", "RUB"),
(50, "GBP", "JPY"),
])
get_rate(from_currency, to_currency) → float
Получить только курс.
rate = c.get_rate("BTC", "USD")
print(rate) # 55862.0
rate_at(on_date, from_currency, to_currency) → float
Исторический курс на конкретную дату.
from datetime import date
from app import Converter
c = Converter()
rate = c.rate_at(date(2023, 1, 1), "USD", "EUR")
print(f"USD/EUR на 1 января 2023: {rate}")
Поддерживается провайдерами
CurrencyAPIProviderиFrankfurterProvider.
invalidate_cache()
Сбросить кэш, чтобы следующий запрос получил свежие курсы.
c.invalidate_cache()
Провайдеры курсов
Провайдер — это источник курсов. Можно использовать готовые или написать свой.
CurrencyAPIProvider (по умолчанию)
from app.providers import CurrencyAPIProvider
provider = CurrencyAPIProvider()
- Источник: github.com/fawazahmed0/exchange-api
- Бесплатно, API-ключ не нужен
- 150+ валют: все основные фиат + BTC, ETH, SOL, BNB, DOGE, ADA и др.
- Поддерживает исторические курсы
- CDN-кэширование на стороне провайдера, лимитов практически нет
FrankfurterProvider
from app.providers import FrankfurterProvider
c = Converter(provider=FrankfurterProvider())
- Источник: frankfurter.app — данные ЕЦБ
- Бесплатно, ключ не нужен
- ~33 фиатные валюты (EUR, USD, GBP, JPY, CNY, ...)
- Не поддерживает: RUB (отключён ЕЦБ в 2022), крипту
- Поддерживает исторические курсы
CoinGeckoProvider
from app.providers import CoinGeckoProvider
c = Converter(provider=CoinGeckoProvider())
- Источник: coingecko.com
- Бесплатно, ключ не нужен (лимит ~10–30 запросов/мин)
- Фокус на криптовалютах: BTC, ETH, SOL, BNB, DOGE, ADA, TON, ...
- Также поддерживает фиат: USD, EUR, RUB, GBP и др.
StaticProvider (для тестов и офлайн)
from app.providers import StaticProvider
provider = StaticProvider({
"USD": {
"EUR": 0.92,
"RUB": 90.0,
"BTC": 0.000022,
}
})
c = Converter(provider=provider)
- Курсы задаются вручную — никакой сети не нужно
- Обратный курс считается автоматически: если есть USD→EUR, то EUR→USD тоже работает
- Идеально для юнит-тестов
Написать свой провайдер
Достаточно унаследоваться от BaseProvider и реализовать один метод:
from app.providers import BaseProvider
from typing import Dict
class MyProvider(BaseProvider):
name = "my-provider"
def get_rates(self, base: str) -> Dict[str, float]:
# base — код базовой валюты в верхнем регистре, например "USD"
# вернуть словарь: {код валюты: курс}
# пример: {"EUR": 0.92, "RUB": 90.0, "USD": 1.0}
rates = fetch_from_my_api(base)
return rates
c = Converter(provider=MyProvider())
Объект ConversionResult
Метод convert() возвращает объект ConversionResult, а не просто число.
| Поле | Тип | Описание |
|---|---|---|
amount |
float |
Итоговая сумма в целевой валюте |
rate |
float |
Курс: сколько to_currency за 1 from_currency |
from_currency |
str |
Исходная валюта (всегда uppercase) |
to_currency |
str |
Целевая валюта (всегда uppercase) |
provider |
str |
Название провайдера |
fetched_at |
datetime |
Время получения курса |
cached |
bool |
Был ли результат из кэша |
result = c.convert(100, "USD", "EUR")
# Использовать значение
print(result.amount) # 85.75
print(result.rate) # 0.8575
# Преобразовать в словарь (удобно для JSON/API-ответов)
data = result.to_dict()
# {
# "amount": 85.75,
# "rate": 0.8575,
# "from_currency": "USD",
# "to_currency": "EUR",
# "provider": "currency-api",
# "fetched_at": "2026-04-09T14:00:00+00:00",
# "cached": False
# }
import json
print(json.dumps(result.to_dict(), indent=2))
Кэширование
По умолчанию курсы кэшируются на 1 час в памяти. Это означает что за час делается только 1 HTTP-запрос на каждую пару валют — не важно сколько раз вызвать convert().
# Кэш на 5 минут
c = Converter(cache_ttl=300)
# Кэш на 24 часа
c = Converter(cache_ttl=86400)
# Без кэша (каждый раз свежий запрос к API)
c = Converter(cache_ttl=0)
# Принудительно сбросить кэш в любой момент
c.invalidate_cache()
CLI — командная строка
После pip install -e . доступна команда converte:
converte 100 USD EUR
# 85.75 EUR (1 USD = 0.8575 EUR, via currency-api)
converte 1 RUB BTC
# 0.00000018 BTC (1 RUB = 1.79e-07 BTC, via currency-api)
converte 1 BTC RUB
# 5586205.94 RUB (1 BTC = 5586206 RUB, via currency-api)
Выбор провайдера:
converte 100 USD EUR --provider frankfurter
converte 1 ETH USD --provider coingecko
Без установки пакета — через Python:
python -m app.cli 100 USD EUR
python -m app.cli 1 RUB BTC
Использование в проектах
FastAPI
from fastapi import FastAPI
from app import Converter
app = FastAPI()
converter = Converter() # создаём один раз при старте
@app.get("/convert")
def convert(amount: float, from_currency: str, to_currency: str):
result = converter.convert(amount, from_currency, to_currency)
return result.to_dict()
Telegram-бот (aiogram)
from aiogram import Router
from app import Converter
router = Router()
converter = Converter()
@router.message()
async def handle(message):
# ожидаем формат: "100 USD EUR"
parts = message.text.split()
if len(parts) == 3:
amount, fc, tc = float(parts[0]), parts[1], parts[2]
result = converter.convert(amount, fc, tc)
await message.answer(str(result))
Скрипт / CLI-утилита
from app import Converter
c = Converter()
# портфель в разных валютах -> итого в USD
portfolio = {"BTC": 0.05, "ETH": 1.2, "RUB": 50000}
total_usd = sum(c.convert(amount, currency, "USD").amount
for currency, amount in portfolio.items())
print(f"Итого: ${total_usd:.2f}")
Jupyter / pandas
import pandas as pd
from app import Converter
c = Converter()
currencies = ["EUR", "RUB", "GBP", "JPY", "BTC", "ETH"]
data = [c.convert(1, "USD", cur).to_dict() for cur in currencies]
df = pd.DataFrame(data)[["to_currency", "rate"]]
print(df)
Разработка и тесты
Запуск тестов
pip install pytest
python -m pytest tests/ -v
Запуск демо
python main.py
Добавить новый провайдер
- Создать файл
app/providers/my_provider.py - Унаследовать от
BaseProvider, реализоватьget_rates() - Добавить в
app/providers/__init__.py
Поддерживаемые валюты (примеры)
Фиат: USD, EUR, RUB, GBP, JPY, CNY, KRW, INR, BRL, CAD, AUD, CHF, TRY, PLN, UAH и 100+ других
Крипто (через CurrencyAPIProvider): BTC, ETH, BNB, SOL, XRP, DOGE, ADA, AVAX, DOT, SHIB, LTC, TRX, UNI, LINK, TON, USDT, USDC и многие другие
Структура проекта
converte_wallet/
├── app/
│ ├── __init__.py # Converter, ConversionResult, MemoryCache
│ ├── converter.py # основной класс Converter
│ ├── models.py # ConversionResult
│ ├── cache.py # MemoryCache с TTL
│ ├── cli.py # CLI entrypoint
│ └── providers/
│ ├── __init__.py # экспорт всех провайдеров
│ ├── base.py # BaseProvider — базовый класс
│ ├── static.py # StaticProvider (офлайн/тесты)
│ ├── currency_api.py # CurrencyAPIProvider (дефолт, 150+ валют)
│ ├── frankfurter.py # FrankfurterProvider (ECB данные)
│ └── coingecko.py # CoinGeckoProvider (крипто)
├── tests/
│ ├── test_converter.py # 14 тестов конвертера
│ └── test_providers.py # 6 тестов провайдеров
├── main.py # демо запуска
├── pyproject.toml # метаданные пакета
├── requirements # зависимости
└── README.md
Лицензия
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file converte_wallet-0.1.0.tar.gz.
File metadata
- Download URL: converte_wallet-0.1.0.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e163eba92f2bdb05601748aa848ac721a0d430412e3807c255aa5cb0c01d1145
|
|
| MD5 |
155ca9cb2dc57d5737c66685861320c6
|
|
| BLAKE2b-256 |
a21ccd4c0b3d86159e53ce4ca61d811e2205d4a3d46364656dd1645c270a9152
|
File details
Details for the file converte_wallet-0.1.0-py3-none-any.whl.
File metadata
- Download URL: converte_wallet-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
319e11b131946cb1805b91915f92c4362957ede8a53a435cabfd76b597524d70
|
|
| MD5 |
7b50fe3d1bdb80d3bda73c5df95c746f
|
|
| BLAKE2b-256 |
a414b59a037a2c5d7be913ce1ab7447843653cfad74b4215f95c5e51a7a1f56b
|