Привет, Хабр! В этой статье я расскажу о возможностях API Magic Eden - одного из крупнейших NFT-маркетплейсов, в статье затрону непосредственно методы соланы, и покажу, как с его помощью можно создавать интересные проекты.

Введение

Magic Eden является ведущим NFT-маркетплейсом с ежемесячным объемом торгов более $100 миллионов. API платформы открывает широкие возможности для разработчиков, позволяя создавать различные приложения: от простых NFT-трекеров до сложных торговых ботов.

Обзор API

Magic Eden API предоставляет доступ к следующим основным категориям данных:

  • Информация о NFT и коллекциях

  • Данные о листингах и предложениях

  • Статистика торгов

  • Информация о кошельках

  • Инструкции для торговых операций

  • Метаданные и аналитика

Базовые эндпоинты

BASE_URL_MAINNET = "https://api-mainnet.magiceden.dev/v2"
BASE_URL_DEVNET = "https://api-devnet.magiceden.dev/v2"

ENDPOINTS = {
    # NFT и коллекции
    "collections": "/collections",
    "collection_stats": "/collections/{symbol}/stats",
    "collection_listings": "/collections/{symbol}/listings",
    
    # Токены
    "token_metadata": "/tokens/{token_mint}",
    "token_listings": "/tokens/{token_mint}/listings",
    "token_offers": "/tokens/{token_mint}/offers",
    
    # Кошельки
    "wallet_tokens": "/wallets/{wallet_address}/tokens",
    "wallet_activities": "/wallets/{wallet_address}/activities",
    
    # Торговые операции
    "create_listing": "/instructions/sell",
    "buy_now": "/instructions/buy_now",
    "place_bid": "/instructions/buy",
}

Настройка и авторизация

Получение API ключа

Для работы с API необходимо получить ключ. Процесс регистрации:

import requests

class MagicEdenClient:
    def __init__(self, api_key: str = None):
        self.base_url = "https://api-mainnet.magiceden.dev/v2"
        self.session = requests.Session()
        if api_key:
            self.session.headers.update({
                'Authorization': f'Bearer {api_key}',
                'Content-Type': 'application/json'
            })

    def _make_request(self, method: str, endpoint: str, **kwargs):
        try:
            response = self.session.request(
                method,
                f"{self.base_url}{endpoint}",
                **kwargs
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"API Error: {e}")
            return None

Основные возможности

1. Работа с коллекциями

class CollectionManager:
    def __init__(self, client: MagicEdenClient):
        self.client = client

    def get_collection_stats(self, symbol: str):
        """Получение статистики коллекции"""
        return self.client._make_request('GET', f'/collections/{symbol}/stats')

    def get_floor_price(self, symbol: str) -> float:
        """Получение минимальной цены в коллекции"""
        stats = self.get_collection_stats(symbol)
        return stats.get('floorPrice', 0) / 1e9 if stats else 0

    def monitor_floor_price(self, symbol: str, interval: int = 60):
        """Мониторинг изменения минимальной цены"""
        while True:
            price = self.get_floor_price(symbol)
            logger.info(f"Floor price for {symbol}: {price} SOL")
            time.sleep(interval)

2. Работа с токенами

class TokenManager:
    def __init__(self, client: MagicEdenClient):
        self.client = client

    def get_token_metadata(self, mint_address: str):
        """Получение метаданных токена"""
        return self.client._make_request('GET', f'/tokens/{mint_address}')

    def get_token_listings(self, mint_address: str):
        """Получение активных листингов токена"""
        return self.client._make_request('GET', f'/tokens/{mint_address}/listings')

    async def monitor_token_price(self, mint_address: str):
        """Асинхронный мониторинг цены токена"""
        while True:
            listings = self.get_token_listings(mint_address)
            if listings:
                min_price = min(listing['price'] for listing in listings)
                logger.info(f"Lowest price for {mint_address}: {min_price} SOL")
            await asyncio.sleep(30)

Идеи для проектов

1. NFT Арбитражный бот

Идея: Поиск ценовых различий между Magic Eden и другими маркетплейсами.

class ArbitrageBot:
    def __init__(self, me_client: MagicEdenClient, other_marketplace_client):
        self.me_client = me_client
        self.other_client = other_marketplace_client
        self.min_profit = 0.5  # Минимальная прибыль в SOL

    async def find_opportunities(self, collection_symbol: str):
        me_listings = await self.me_client.get_collection_listings(collection_symbol)
        other_listings = await self.other_client.get_collection_listings(collection_symbol)

        for me_listing in me_listings:
            for other_listing in other_listings:
                if me_listing['tokenMint'] == other_listing['tokenMint']:
                    profit = other_listing['price'] - me_listing['price']
                    if profit > self.min_profit:
                        await self.execute_arbitrage(me_listing, other_listing)

2. NFT Снайпер

Идея: Автоматическая покупка NFT по заданным критериям.

class NFTSniper:
    def __init__(self, client: MagicEdenClient):
        self.client = client
        self.target_collections = []
        self.max_prices = {}

    async def add_target(self, collection: str, max_price: float):
        self.target_collections.append(collection)
        self.max_prices[collection] = max_price

    async def monitor_listings(self):
        while True:
            for collection in self.target_collections:
                listings = await self.client.get_collection_listings(collection)
                for listing in listings:
                    if listing['price'] <= self.max_prices[collection]:
                        await self.buy_nft(listing)
            await asyncio.sleep(1)

    async def buy_nft(self, listing):
        try:
            instruction = await self.client.get_buy_instruction(listing['tokenMint'])
            # Выполнение транзакции покупки
            transaction = await self.execute_transaction(instruction)
            logger.info(f"Successfully bought NFT: {listing['tokenMint']}")
        except Exception as e:
            logger.error(f"Failed to buy NFT: {e}")

Все выше перечисленное, является примером части какого-то большого кода приложения и тут описан лишь примерный алгоритм, что бы дать вам почву для размышлений.

Лучшие практики

  1. Обработка ошибок и повторные попытки:

from tenacity import retry, stop_after_attempt, wait_exponential

class RobustClient:
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
    async def make_request(self, endpoint: str):
        try:
            response = await self.session.get(f"{self.base_url}{endpoint}")
            response.raise_for_status()
            return response.json()
        except Exception as e:
            logger.error(f"Request failed: {e}")
            raise
  1. Кэширование данных:

from functools import lru_cache
import time

class CachedClient:
    @lru_cache(maxsize=100)
    def get_collection_stats(self, symbol: str):
        return self.client._make_request('GET', f'/collections/{symbol}/stats')

    def clear_cache(self):
        self.get_collection_stats.cache_clear()
  1. Управление rate limits:

class RateLimitedClient:
    def __init__(self, max_requests_per_minute: int = 120):
        self.requests = []
        self.max_requests = max_requests_per_minute

    async def make_request(self, endpoint: str):
        now = time.time()
        # Очистка старых запросов
        self.requests = [req for req in self.requests if now - req < 60]
        
        if len(self.requests) >= self.max_requests:
            wait_time = 60 - (now - self.requests[0])
            await asyncio.sleep(wait_time)
        
        self.requests.append(now)
        return await self._make_request(endpoint)

Заключение

Magic Eden API предоставляет мощные инструменты для создания различных NFT-приложений. Мы рассмотрели основные возможности API и примеры их использования, а также поделились идеями для создания проектов.

Полезные ссылки:

P.S.

Если у вас есть вопросы или вы хотите поделиться своим опытом работы с Magic Eden API, пишите в комментариях.

Комментарии (0)