Интеграция с ChangeNOW API

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1306 услуг
Интеграция с ChangeNOW API
Простой
~2-3 дня
Часто задаваемые вопросы

Направления блокчейн-разработки

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1285
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1122
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    859

Интеграция с ChangeNOW API

ChangeNOW — один из крупнейших поставщиков non-custodial crypto-to-crypto обмена. Интеграция с их API позволяет добавить функциональность обмена в ваш кошелёк, обменник или платформу без необходимости строить собственную ликвидность с нуля.

Базовая интеграция

Получение курса

import httpx
from decimal import Decimal

class ChangeNOWClient:
    BASE_URL = "https://api.changenow.io/v2"

    def __init__(self, api_key: str):
        self.api_key = api_key
        self.headers = {"x-changenow-api-key": api_key}

    async def get_estimated_amount(
        self,
        from_currency: str,  # 'btc'
        to_currency: str,    # 'eth'
        from_amount: float,
        flow: str = 'standard'  # 'standard' или 'fixed-rate'
    ) -> dict:
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.BASE_URL}/exchange/estimated-amount",
                params={
                    "fromCurrency": from_currency.lower(),
                    "toCurrency": to_currency.lower(),
                    "fromAmount": str(from_amount),
                    "flow": flow,
                    "type": "direct"
                },
                headers=self.headers
            )
        data = response.json()

        if "error" in data:
            raise ChangeNOWError(f"{data['error']}: {data.get('message', '')}")

        return {
            "estimated_amount": data["toAmount"],
            "rate": data["toAmount"] / from_amount,
            "min_amount": data.get("minAmount"),
            "max_amount": data.get("maxAmount"),
            "network_fee": data.get("networkFee")
        }

Создание обмена

async def create_exchange(
    self,
    from_currency: str,
    to_currency: str,
    from_amount: float,
    to_address: str,
    refund_address: str = None,
    flow: str = 'standard',
    user_id: str = None
) -> dict:
    payload = {
        "fromCurrency": from_currency.lower(),
        "toCurrency": to_currency.lower(),
        "fromAmount": str(from_amount),
        "address": to_address,
        "flow": flow,
        "type": "direct",
        "extraId": "",  # memo/tag для XRP, EOS, etc.
    }

    if refund_address:
        payload["refundAddress"] = refund_address

    # userId — для отслеживания конверсий affiliate
    if user_id:
        payload["userId"] = user_id

    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{self.BASE_URL}/exchange",
            json=payload,
            headers=self.headers
        )
    data = response.json()

    return {
        "order_id": data["id"],
        "deposit_address": data["payinAddress"],
        "deposit_amount": data["fromAmount"],
        "receive_amount": data["toAmount"],
        "payin_extra_id": data.get("payinExtraId"),  # memo для некоторых сетей
        "status": data["status"]
    }

Мониторинг статуса

async def get_exchange_status(self, order_id: str) -> dict:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"{self.BASE_URL}/exchange/by-id",
            params={"id": order_id},
            headers=self.headers
        )
    data = response.json()

    # Маппинг статусов ChangeNOW к внутренним
    status_map = {
        "waiting": "awaiting_deposit",
        "confirming": "confirming",
        "exchanging": "processing",
        "sending": "sending",
        "finished": "completed",
        "failed": "failed",
        "refunded": "refunded",
        "verifying": "kyc_required"
    }

    return {
        "status": status_map.get(data["status"], data["status"]),
        "payin_hash": data.get("payinHash"),
        "payout_hash": data.get("payoutHash"),
        "amount_received": data.get("amountReceived"),
        "amount_sent": data.get("amountSent"),
        "updated_at": data.get("updatedAt")
    }

Список поддерживаемых валют

async def get_currencies(self, active: bool = True) -> list[dict]:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"{self.BASE_URL}/exchange/currencies",
            params={"active": str(active).lower(), "flow": "standard"},
            headers=self.headers
        )
    currencies = response.json()
    return [
        {
            "ticker": c["ticker"],
            "name": c["name"],
            "network": c.get("network"),
            "image": c.get("image"),
            "is_stable": c.get("isStable", False)
        }
        for c in currencies
    ]

Минимальные суммы и валидация

async def validate_exchange_params(
    self,
    from_currency: str,
    to_currency: str,
    from_amount: float
) -> ValidationResult:
    range_data = await self.get_range(from_currency, to_currency)

    if from_amount < range_data["min_amount"]:
        return ValidationResult(
            valid=False,
            error=f"Amount too small. Min: {range_data['min_amount']} {from_currency.upper()}"
        )

    if range_data.get("max_amount") and from_amount > range_data["max_amount"]:
        return ValidationResult(
            valid=False,
            error=f"Amount too large. Max: {range_data['max_amount']} {from_currency.upper()}"
        )

    return ValidationResult(valid=True)

async def get_range(self, from_currency: str, to_currency: str) -> dict:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"{self.BASE_URL}/exchange/range",
            params={"fromCurrency": from_currency, "toCurrency": to_currency, "flow": "standard"},
            headers=self.headers
        )
    data = response.json()
    return {"min_amount": data["minAmount"], "max_amount": data.get("maxAmount")}

ChangeNOW поддерживает 850+ монет, Standard и Fixed Rate режимы, реферальную программу (35-40% от маржи), и имеет хорошо документированный API. Для быстрого старта обменника — оптимальный первый провайдер ликвидности.