Skip to content

ADR-003 Выбор схемы базы (Tokens & Proxies Data Store) [DRAFT]

Прокси-контракт если относится к токену (через "target_address) то нужно возвращать именно прокси, а не token.

Нюансы

  • collate="c"
  • pg_trgm USING gin (col gin_trgm_ops);

Проблемы:

  • Проблема ilike поиск, занимает 700мс
  • Насколько оправданы join-ы
  • Foreign key на партиции надо или нет?

Виды запросов пользователей

  1. Получить токен по token.address + network и вернуть meta. Для отображения мета-информации о текущем токене.
  2. Поиск token по имени (name и/или symbol ) - ‘usdt’. ILIKE(%%). Для актокомплита.
  3. Дай мне “Адрес баланса” с метаданными токена по ilike name/symbol сортированные по верифицированности, и имени токена. Типовой запрос которым бегают пользователи, зависит от пользовательской нагрузки. По прокси сортировать не требуется. Нагрузка в пике 100 запросов в минуту.

Расчет нагрузки:

Желаемое время ответа 300ms-500ms. 4-5 тыс обменов в день. Каждый 30% делает обмен. 15 тыс клиентов в день. В среднем 4 поиска на обмен. 2 тыс в час в течении 8-ми часов. 30 минуту. В пике 100 в минуту.

Термины:

  • “Адрес баланса” - адрес токена или прокси, в случае если для него не установлен прокси-адрес. В случае если установлен это прокси.

Сущность token

Хранит метаинформацию (иконки, макретинг) о токенах, их адресах, сеть.

У одного токена может быть несколько прокси которые на него ссылаются.

Количество - 2-3 млн.

Поля:

  1. id - uuidv7
  2. address - hexstring 42
  3. network - (1 из 6 сетей) string/enum
  4. is_verified boolean, верифицирован ли он в блокчейн эксплорере

meta attributes: - txid - создавамая транзакция - symbol nullable могут быть пустыми - name nullable могут быть пустыми - decimals nullable - creator (address) - created_at - updated_at - block_number - когда создался

Индексы:

  • (address + network) - unique

Сущность proxy

Один прокси может ссылаться только на один token. На один token может ссылаться много proxy.

Количество - 5-6 млн.

  1. id
  2. address - адрес proxy
  3. name nullable - используется если у токена нет
  4. symbol nullable - используется если у токена нет
  5. decimals nullable
  6. network
  7. token_address nullable (он-же target_address, токен еще не появился умуте), может ссылаться на не существующий токен.

Индексы:

  • (network, token_address)
  • (network, ddress) - composite primary key, unique априори уникален

Один прокси только для одного адреса.

meta attributes: - proxy_type

Сущность "Адрес обмена" (композит)

  • name - token.name || proxy.name
  • symbol - token.symbol || proxy.symbol
  • address - proxy.address || token.address
  • decimals - proxy.decimals || token.decimals

Вариант 1 (tokens, proxies, balance_addresses)

Бенчмарк - https://github.com/safeblock-com/token-db-schema-selection

Вариант 2 (tokens + proxies в одной таблице)

Таблица contacts (общая, tokens + proxy)

Поля:

  1. id - uuidv7
  2. address - hexstring 42
  3. network - (1 из 6 сетей) string/enum
  4. is_proxy boolean
  5. proxy_type - string/enum (10 штук, пополняется редко) ['ip701', 'ip702', ..]
  6. targed_address foreign key uuidv7 optionl если это proxy - может меняться.

meta attributes:

  • txid - создавамая транзакция
  • symbol - citext
  • name - citext
  • decimals
  • creator (address)
  • created_at
  • updated_at
  • block_number - когда создался

Индексы:

  • (address + network) - unique

На поиск пары

  1. address=a targed_address=nil is_proxy=false
  2. address=b targed_address=nil is_proxy=true
  3. address=c targed_address=a is_proxy=true
  4. address=d targed_address=nil is_proxy=false

Пользователь вводит получение пар между a и d.

Мы должны вернуть пару c-d

select * from contracts where network='binance' and (address='a' and not is_proxy) or (target_address='a' and is_proxy) order by is_proxy;

Поисковый

Поиск по адресу:

Ищет a мы возвращаем c

select * from contracts where network='binance' and (address='a' and not is_proxy) or (target_address='a' and is_proxy) order by is_proxy limit 1;

Индексы:

  • (network, address, is_proxy)
  • (network, target_address, is_proxy)

Поиск по имени:

Ищет a мы возвращаем c

select * from contracts where network='binance' and (address='a' and not is_proxy) or (target_address='a' and is_proxy) order by is_proxy limit 1;

Индексы:

  • (network, name, is_proxy)

Ссылки