
Kontekst
Bindaro to nasz własny produkt: miejsce, w którym posiadacz NFT układa je w album, opisuje, publikuje wynik i daje się znaleźć innym kolekcjonerom. Pod spodem siedzi marketplace, model rzadkości i punktacji, silnik analityczny oraz bot na Discordzie, dostarczone jako aplikacja webowa i aplikacje mobilne na Androida i iOS.
Problem
Kolekcjoner ma już portfel i marketplace. Nie ma miejsca, w którym kolekcja jest obiektem kuratorowanym, a nie listą posiadanych tokenów posortowaną po adresie kontraktu. To problem produktowy, który niemal natychmiast rozpada się na trzy inżynierskie.
Pierwszy: blockchain jest fatalnym modelem odczytowym. Własność, metadane, ceny podłogi i historia aktywności mieszkają w różnych miejscach, docierają w różnym tempie i bywają ze sobą niezgodne; pytanie łańcucha w momencie renderowania strony daje produkt, który jest wolny, kiedy działa, i pusty, kiedy węzeł ma zły dzień.
Drugi: tożsamość. Odbiorcy dzielą się na tych, którzy przychodzą z portfelem, i tych, którzy przychodzą z adresem e-mail i bez zamiaru uczenia się, czym jest seed phrase. Obsługa wyłącznie pierwszych to produkt dla ludzi, którzy mają już trzy takie. Obsługa wyłącznie drugich oznacza, że platforma nie potrafi udowodnić, że ktokolwiek cokolwiek posiada.
Trzeci: analityka. Rzadkość, wycena i sygnały zakupowe są powodem, dla którego produkt otwiera się drugi raz. Robienie tego przez hostowane API modelu oznacza, że przy każdym zapytaniu portfel użytkownika i wyprowadzona z niego sytuacja finansowa opuszczają naszą infrastrukturę, a koszt rośnie wraz z ciekawością, nie z przychodem.
Podejście
Odczyt łańcucha schowaliśmy za własnym stanem. Backend na Quarkusie, PostgreSQL jako model odczytowy z migracjami trzymanymi w repozytorium, Redis na to, czego nie warto liczyć ponownie, S3 na media. Aplikacje rozmawiają z GraphQL i REST, nigdy z węzłem. To sprawia, że strona albumu otwiera się w tempie strony, a nie w tempie łańcucha, i to samo powoduje, że produkt degraduje się łagodnie, zamiast padać, kiedy źródło zwalnia.
Tożsamość rozwiązaliśmy przez niewybieranie. Z przodu stoi Keycloak, przyjmując podpis portfela, kod OTP na e-mail i logowanie społecznościowe jako metody uwierzytelnienia jednego konta, z portfelem osadzonym, tworzonym dla tych, którzy przychodzą bez własnego. Strona podpisowa to osobna praca z własnym opisem; z perspektywy Bindaro istotne jest, że platforma ma jeden rejestr użytkowników, jeden ślad audytowy i jedno miejsce odbierania dostępu.
Silnik analityczny, BindaroAI, działa na naszej infrastrukturze na modelach self-hosted i była to decyzja architektoniczna, nie optymalizacja kosztu. Osiem funkcji: rekomendacje, wgląd w rzadkość, sygnały cenowe, klasyfikacja, wycena, porównanie kolekcji, wykrywanie wzorców i kuratorskie ekspozycje, z których każda jest promptem po danych, które już mamy, przy niskiej temperaturze, bo wynik ma być na tyle powtarzalny, żeby dało się z nim polemizować. Kolekcja użytkownika nie jest wsadem do cudzego serwisu.
Mechaniki rynkowej nie wymyślaliśmy od nowa: oferty i wystawienia działają na Seaporcie, obejmując ERC-721 i ERC-1155, więc powiernictwo i rozliczenie idą protokołem, który audytowali ludzie robiący to zawodowo.
Strona kliencka to jedno monorepo, aplikacja webowa w Next.js i aplikacja Expo wydawana do Play Store i TestFlight, dzielące klienta API, auth, system projektowy i tłumaczenia jako pakiety. Aplikacja mobilna nie jest opakowaniem strony i nie jest drugą bazą kodu udającą zgodność z pierwszą.
Rezultat
Produkt działa produkcyjnie w wersji webowej, w otwartych testach na Androidzie i w zamkniętych na iOS, na backendzie liczącym ponad tysiąc sto źródeł Javy i dwieście trzydzieści dziewięć migracji schematu, co jest uczciwszą miarą rzeczywistej powierzchni platformy niż lista funkcji.
Koszty tych decyzji są widoczne. Własny model odczytowy to własny problem uzgadniania: każde odświeżenie metadanych, każda cena podłogi, każda zmiana własności są czymś, co musimy utrzymywać w zgodzie z łańcuchem, i nie ma wersji tego zadania, która jest darmowa. Inferencja u siebie oznacza, że sprzęt, aktualizacje modeli i budżet opóźnień są nasze, zamiast płacić komuś, żeby były jego.
Wnioski
W produkcie stojącym na danych publicznych pytaniem architektonicznym jest, gdzie mieszka autorytatywny model odczytowy. Odpowiedź wczesna sprawia, że wszystko dalej jest cachem ze znaną historią odświeżania. Odpowiedź późna, przez dokładanie cache'ów tam, gdzie strona wydawała się wolna, daje system, w którym nikt nie potrafi powiedzieć, co jest prawdą.
Drugi wniosek dotyczy funkcji AI w produkcie konsumenckim. Ciekawą decyzją prawie nigdy nie jest, który model, tylko co wychodzi poza budynek. Kiedy w żądaniu są posiadane aktywa i wyprowadzona z nich zamożność, wybór dostawcy przestaje być pytaniem zakupowym, a staje się architektonicznym.