Na Solanie, gdzie co sekundę powstaje tysiące transakcji, jeśli próbujesz monitorować wszystkie aktualizacje kont na całym świecie, Twój robot szybko zatonie w ogromnym szumie danych. Ograniczenia przepustowości węzłów RPC, obciążenie CPU przy analizie oraz opóźnienia sieci mogą natychmiast zniszczyć możliwość arbitrażu.

Efektywny Searcher nigdy nie „słucha na ślepo“. Wykorzystuje strategię zwaną „monitoring sterowany zapasami (Inventory-Driven Monitoring)“: najpierw offline tworzy globalny indeks puli płynności na całym sieci, filtrowanie wysoce wartościowych „kandydatów do arbitrażu“, a następnie dokonuje precyzyjnej subskrypcji.

Artykuł ten rozłoży na czynniki, jak zbudować ten system Inventory o wysokiej wydajności.

1. Kluczowa idea: Zmniejszenie pola bitwy, zablokowanie punktów zwycięstwa

1.1 Dlaczego warto zbudować Inventory?

DEX (zdecentralizowane giełdy) na Solanie, takie jak Raydium i Orca, mają tysiące pul płynności. Jednak dla strategii arbitrażowych tylko te pary handlowe, które istnieją jednocześnie w wielu protokołach (na przykład SOL/USDC, które ma pulę na Raydium i również na Orca), mają przestrzeń na arbitraż atomowy.

Zadaniem Inventory jest:

  • Zimne uruchomienie agregacji: Uzyskaj pełną listę pul z API różnych DEX.

  • Obliczenie przecięcia: Zidentyfikuj nakładające się pary handlowe tokenów.

  • Filtracja białej listy: Usuń zombi pule, pule o niskiej płynności, tworząc „białą listę do nasłuchiwania”.

1.2 Napędzany przez zapasy vs. Napędzany przez całość

  • Napędzany przez całość: Subskrybuj wszystkie logi, odkrywaj okazje, a następnie przeszukuj tabelę. Zaletą jest szeroki zasięg, wadą jest bardzo wysokie opóźnienie i przetwarzanie dużej ilości zbędnych danych.

  • Napędzany przez zapasy: Subskrybuj tylko aktualizacje kont w białej liście. Zaletą jest bardzo szybka reakcja i oszczędność zasobów RPC, co czyni go preferowanym wyborem do arbitrażu wysokiej częstotliwości.

2. Architektura technologiczna: Wysokowydajna maszyna stanów oparta na Rust

W silniku wykonawczym Rust moduł Inventory został zaprojektowany jako singleton o wysokiej współbieżności i bezpieczny dla wątków, aby mogły go współdzielić różne moduły strategii.

2.1 Kluczowe struktury danych: DashMap i Arc

Ponieważ przetwarzanie danych w Solanie jest wielowątkowe i równoległe, Inventory musi obsługiwać bardzo wysoką częstotliwość odczytu i zapisu:

  • DashMap: To wysokowydajna współbieżna tabela haszowa. W porównaniu do standardowego HashMap + Mutex, szczegółowość blokad jest zmniejszona do poziomu fragmentacji (Shard), co zapobiega globalnej rywalizacji blokad w czasie wysokiej częstotliwości analizy stanu.

  • Arc (Atomic Reference Counted): Używane do bezpiecznego dzielenia się adresem pamięci Inventory pomiędzy różnymi zadaniami Tokio (takimi jak zadania nasłuchujące, zadania wyceny, zadania wykonawcze), realizując dostęp do danych bez kopiowania.

2.2 Logiczk warstw indeksu

System wewnętrzny utrzymuje dwa poziomy indeksów:

  1. Globalny Indeks Pul: Rejestruje mapowanie adresu puli do metadanych tokenów (Mint, Decimals, Vault).

  2. Mapa Par Arbitrażowych: Rejestruje „kandydatów na pary arbitrażowe”. Na przykład wprowadź adres Mint SOL, aby natychmiast uzyskać powiązane informacje o jego pulach w Raydium A i Orca B.

3. Implementacja algorytmu: szybkie przecięcie O(N+M)O(N+M)

Kluczowym elementem budowy białej listy arbitrażu jest „znalezienie przecięcia”.

  1. Skanowanie protokołu A (Raydium): Zapisz wszystkie pule w tymczasowej tabeli haszowej według Token_A -> Pool_Address.

  2. Skanowanie protokołu B (Orca): Przejrzyj listę pul, jeśli w tabeli haszowej protokołu A znajdziesz ten sam Token_A, to trafisz na potencjalną szansę arbitrażu.

  3. Generowanie Watchlist: Dodaj jednocześnie adresy obu trafionych pul do „listy do nasłuchiwania (Watchlist)”.

Złożoność czasowa: Wystarczą tylko dwa skanowania liniowe, aby zakończyć, nawet w obliczu dziesiątek tysięcy pul, można to zrobić w czasie milisekund.

4. Punkty optymalizacji wydajności: prędkość z detali inżynieryjnych

4.1 Pamięć podręczna API i tolerancja błędów

Oficjalne API protokołów takich jak Raydium często nie jest wystarczająco stabilne. Wprowadziliśmy lokalną pamięć podręczną z trwałością w implementacji inżynieryjnej.

  • Podczas zimnego uruchomienia priorytetowo odczytaj lokalny pools_cache.json.

  • W tle asynchroniczne żądanie aktualizacji pamięci podręcznej API.

  • To zapewnia, że nawet w ekstremalnych warunkach sieciowych robot może natychmiast wznowić pracę.

4.2 Ograniczenia subskrypcji i fragmentacja

Większość węzłów RPC ma ograniczenia dotyczące liczby subskrypcji accountSubscribe dla pojedynczego połączenia (na przykład 50-100).
Inventory automatycznie sortuje Watchlist na podstawie „gorączki puli (wolumen/TVL)”, priorytetowo subskrybując N pul o największym potencjale zysku, lub rozpraszając subskrypcje na wiele węzłów RPC za pomocą równoważenia obciążenia.

5. Demonstracja prototypu algorytmu (realizacja w Pythonie)

Choć w środowisku produkcyjnym używamy Rust, jego podstawowa logika może być jasno wyrażona w poniższym przykładzie w Pythonie:

from dataclasses import dataclass
from typing import Dict, List, Set

@dataclass(frozen=True)
class PoolMetadata:
address: str
token_mint: str

def build_arbitrage_radar(ray_pools: List[PoolMetadata], orca_pools: List[PoolMetadata]):
# 1. Budowanie indeksu Raydium (Token -> Pool)
ray_index = {p.token_mint: p.address for p in ray_pools}

arbitrage_watchlist = []

# 2. Skanowanie Orca w poszukiwaniu przecięcia
for o_pool in orca_pools:
if o_pool.token_mint in ray_index:
# Znalazłem nakładanie się: ten token ma płynność na obu DEX
arbitrage_watchlist.append({
"token": o_pool.token_mint,
"raydium_pool": ray_index[o_pool.token_mint],
"orca_pool": o_pool.address
})

return arbitrage_watchlist

# Mock dane do wyświetlenia
ray_list = [PoolMetadata("RAY_SOL_POOL", "SOL_MINT"), PoolMetadata("RAY_BONK_POOL", "BONK_MINT")]
orca_list = [PoolMetadata("ORCA_SOL_POOL", "SOL_MINT"), PoolMetadata("ORCA_WIF_POOL", "WIF_MINT")]

watchlist = build_arbitrage_radar(ray_list, orca_list)
print(f"[*] Znaleziono {len(watchlist)} potencjalnych ścieżek arbitrażu")
# Wyjście będzie zawierać ścieżki SOL, ponieważ oba DEX mają pulę SOL

6. Podsumowanie: Radar jest włączony

Moduł Inventory jest „filtr” całego systemu MEV, który filtruje hałas z całej sieci, pozostawiając tylko cele lśniące zyskiem.

  • Brak Inventory: Twój robot przetwarza tysiące nieistotnych informacji bez celu.

  • Posiadając Inventory: Twój robot koncentruje się tylko na kilkudziesięciu pulach o wysokiej zmienności, gotowy do działania w każdej chwili.

Zapowiedź następnego kroku

Mając białą listę, następnym krokiem jest jak na bieżąco uchwycić zmiany tych kont. W następnym artykule przejdziemy do modułu Scout, aby wyjaśnić, jak poprzez protokół gRPC/WebSocket osiągnąć submilisekundowe monitorowanie transakcji i analizę danych.

Artykuł napisany przez Levi.eth, koncentrując się na praktykach inżynieryjnych o wysokiej wydajności w ekosystemie Solana.