Запросы к этому посту можно найти здесь — https://dune.xyz/queries/153902

Проведя некоторое время в стране NFT, я жажду узнать что-то новое.

Горячей темой в последнее время был выпуск протоколов Ethereum Layer 2, и я нашел очень хорошую панель инструментов, которая кажется идеальной для погружения.

Панель инструментов называется Optimistic-Ethereum, а ее автор — «@Marcov».

Прежде чем углубиться, я хотел немного объяснить, как я обучаюсь и почему я пишу здесь. После просмотра запросов из примера панели инструментов я пишу их с нуля самостоятельно. Я хочу убедиться, что могу заставить запрос выполняться так же, как автор, и это дает мне возможность попрактиковаться и работать над ошибками. Публикация объяснений на Medium еще больше укореняет мое понимание, а также имеет для меня смысл, если помогает хотя бы одному человеку. Я всегда буду поощрять написание запросов вместо того, чтобы читать о них и предполагать, что вы понимаете.

Хорошо, давайте погрузимся.

Всего транзакций в день. По аналогии с таблицей «транзакций» Эфириума существует соответствующая таблица под названием «оптимизм» «транзакции». Очень удобно. Как только вы найдете эту таблицу, расчеты количества транзакций будут довольно простыми SQL.

 select 
date_trunc(‘day’,”block_time”) as “day”
, count(*)
from optimism.”transactions”
group by date_trunc(‘day’,”block_time”)
order by “day” asc

Уникальных пользователей в день. В этом разделе используется та же таблица, что и в запросе транзакций выше, но вместо подсчета строк в таблице транзакций мы будем подсчитывать отдельный (уникальный) адрес в столбце «от». Чтобы убедиться, что мы не дважды погружаем пользователей в несколько дней (следовательно, уникальных пользователей), мы сначала выбираем группировку min(block_time) по «от», чтобы получить только первый день, когда новый адрес использовался Optimism. Затем мы можем суммировать пользователей за каждый день и, наконец, использовать предложение over, чтобы сделать эту сумму кумулятивной.

with first_tx as (
 select min(“block_time”) as “min_block_time”
 , “from” 
 from optimism.”transactions”
 group by “from”),
users as (select date_trunc(‘day’,”min_block_time”) as “day”
, count(*) as users
from first_tx
group by date_trunc(‘day’,”min_block_time”))
select sum(users) over (order by “day”) as “cum_users”
, “day”
from users

Средняя стоимость транзакции. Снова та же таблица, что и для транзакций, и похожа на количество транзакций и уникальных пользователей, но на этот раз рассчитывается количество газа ETH по формуле (gas_limit*gas_cost)/10¹⁸. Автор также включил среднюю стоимость транзакции Uniswap, которая представляет собой тот же запрос, но с добавлением WHERE «to» = адрес контракта Uniswap.

select
avg((“gas_limit”*”gas_price”)/10¹⁸) as eth_gas_price
, date_trunc(‘day’,”block_time”) as “day”
from optimism.”transactions”
group by date_trunc(‘day’,”block_time”)

Я немного удивился, почему автор не включил конверсию в доллары США, поэтому я решил попробовать. Таблица Prices.usd пока недоступна в базе данных Optimism, поэтому мне пришлось искать альтернативу. Я нашел таблицу dune_user_generated.»uniswap_prices», которая казалась многообещающей, и на самом деле она работала. Я создал подвыбор ниже и присоединился к нему на основе дня, чтобы рассчитать цену газа в долларах США.

SELECT max(price) as price
 , “day”
 from dune_user_generated.”uniswap_prices”
 where “symbol”=’ETH’
 group by “day”

ETH об оптимизме. Теперь все становится немного интереснее. В этом запросе мы используем таблицу с именем optimism.logs. Автор использует поле «block_time», данные, тему и адрес контракта.

Поле data представляет стоимость транзакции и делится на 10¹⁸, чтобы получить значение ETH. Поле данных также преобразуется в тип «byte2numeric», который необходим для выполнения вычисления деления, поскольку вы не можете разделить поле «bytea».

В полях topic автор проводит различие между сжиганием ETH и выпуском ETH. Мое понимание функции L2 заключается в том, что когда вы соединяете свои активы, активы временно сжигаются в цепочке L1 и чеканятся в цепочке L2, а когда вы выходите, происходит обратное. Когда «topic3» = адрес записи, ETH записывается на L2. Затем «topic2» = адрес записи, после чего ETH чеканится на L2. Поле «данные» отрицательное (-) для ожогов и положительное (+) для монетных дворов.

Адрес контракта в предложении where представляет адрес контракта ETH на Optimism. Чтобы подтвердить это, я использовал версию Etherscan для оптимизма (весело!) https://optimistic.etherscan.io.

Когда вы объединяете чеканку и сжигание транзакций, вы получаете оставшийся ETH на Optimism.

with mints as (
 select bytea2numeric(“data”)/1e18 as “eth”
 , date_trunc(‘day’,”block_time”) as “day”
 from optimism.”logs”
 where “contract_address”= ‘\x4200000000000000000000000000000000000006’ — ETH
 and “topic2”= ‘\x0000000000000000000000000000000000000000000000000000000000000000’
 )
, burns as (
 select -1 * bytea2numeric(“data”)/1e18 as “eth”
 , date_trunc(‘day’,”block_time”) as “day”
 from optimism.”logs”
 where “contract_address”= ‘\x4200000000000000000000000000000000000006’ — ETH
 and “topic3”= ‘\x0000000000000000000000000000000000000000000000000000000000000000’

Total Elements. Для меня это была новая концепция. Мы не уверены, что такое «элемент».

Из краткого изучения используемых таблиц видно, что каждая «пакетная» транзакция содержит переменное количество «элементов». Я не совсем уверен, правильно ли это, но я предполагаю, что каждый элемент представляет собой одну транзакцию, которая объединяется в пакеты и отправляется в цепочку L1 в виде сверток.

Таблица, используемая в этих объектах, уникальна тем, что не отображается при поиске в проводнике. А еще у него ужасно длинное имя.

OVM_CanonicalTransactionChain_evt_TransactionBatchAppended — в этой таблице есть каждый отдельный пакет с соответствующим количеством элементов. Существует столбец под названием _prevTotalElements, который представляет собой промежуточную сумму элементов в каждом пакете.

Чтобы показать Total Elements, вы просто выбираете первую строку в таблице, упорядоченную по evt_block_time.

select “_prevTotalElements”
from optimism.”OVM_CanonicalTransactionChain_evt_TransactionBatchAppended”
order by evt_block_time desc 
limit 1

Чтобы показать кумулятивную сумму элементов, вы можете агрегировать максимальное значение за каждый день без необходимости суммировать () по (), потому что, как я уже упоминал, столбец уже является кумулятивным.

select max(“_prevTotalElements”) as “cum_elements”
, date_trunc(‘day’,”evt_block_time”) as “day”
from optimism.”OVM_CanonicalTransactionChain_evt_TransactionBatchAppended”
group by date_trunc(‘day’,”evt_block_time”)
order by date_trunc(‘day’,”evt_block_time”) asc

Размер пакета. Это измерение также берется из таблицы OVM_Canonical и измеряется в столбце «_batchSize». Это не кумулятивный столбец, и на основе данных, которые в настоящее время находятся в этом поле, максимальное значение равно 251. Я считаю, что это представляет собой общий размер транзакций («элементов»), которые могут быть включены в каждую партию, которая должна увеличиваться в течение время, когда Оптимизм выходит за рамки своей бета-фазы.

Время между пакетами. Опять же, мы используем каноническую таблицу. В этом расчете используется «новая для меня» функция под названием «задержка», которая позволяет вам динамически выбирать из предыдущей строки данных (довольно круто). Автор вычитает evt_block_time-lag(evt_block_time) из (в порядке возрастания evt_block_time), чтобы получить время между каждым пакетом. Затем автор включает «день» транзакций, а затем суммирует и усредняет «batch_time» для каждого дня.

with batches as (select date_trunc(‘day’,”evt_block_time”) as “day”
, “evt_block_time” — lag(“evt_block_time”) over (order by “evt_block_time” asc) as “batch_time”
from optimism.”OVM_CanonicalTransactionChain_evt_TransactionBatchAppended”)
select “day”
, avg(“batch_time”) as “avg_batch_time”
from batches
group by “day”
order by “day” asc

Вот и все. Моя философия всегда заключалась в том, что вы действительно не узнаете, пока не попробуете. Попадая туда и выполняя запросы, я получаю самые ценные уроки.

Примечание. При использовании функции «Выполнить по выбору» я продолжал получать сообщение об ошибке, показанной ниже. Не уверен, что это уникально для схемы Optimism или даже для таблицы OVM. Когда я скопировал запросы в «Новый запрос» и запустил весь блок, они работали нормально. Не знаю, почему это происходило. Ошибка: связь "optimism.OVM_CanonicalTransactionChain_evt_TransactionBatchAppended" не существует в строке 3, позиция