Сталкивались ли вы с проблемой подтверждения ускорения и отмены транзакций? Не смотри больше! Вот решение

Недавно я отвечал за создание системы, позволяющей отслеживать отмененные и ускоряющие транзакции? Вы не знаете, о чем я говорю? Вы счастливый мужчина/женщина (или безответственный). Возможно, вы просто не учли существование проблемы. Позвольте мне рассказать вам, о чем я говорю.

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

  1. Ускорься,
  2. Отмена.

Начнем с самого начала.

Идеальный сценарий

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

Эфириум Транзакция

Чтобы лучше понять проблему, мы должны изучить, как транзакции в Ethereum выглядят внутри. Помимо данных, значения, от, до, газа, gasLimit и т. д., они также имеют два важных свойства. Его одноразовый номер и хэш транзакции. Нонс — это просто счетчик транзакций, совершенных с заданного адреса, которые защищают от атаки двойного расхода, а хеш транзакции — это просто хэш, отсчитываемый от всех остальных свойств.

Ускорить

Поскольку все колеблется вокруг денег, Эфириум ничем не отличается. Когда дело доходит до порядка проведения транзакций, майнеры выбирают самые прибыльные транзакции, то есть те, у которых самая высокая стоимость газа. Допустим, вы совершили транзакцию, но она долгое время не подтверждалась. Вы хотите ускорить его, так что вы… Что именно вы здесь делаете, кроме того, что нажимаете кнопку ускорения?

Вы создаете 2-ю транзакцию с тем же одноразовым номером и более высоким газом, надеясь, что майнеры подхватят ее быстрее. Так как хэш рассчитывается по всем параметрам, он будет отличаться от первой транзакции, потому что газ другой. Задача начинается здесь. Поскольку вы можете ускорить транзакцию буквально с каждой страницы, просто используя Metamask, нет никакого способа получить эту информацию в приложении из Metamask. Мы должны подойти к этому по-другому.

Отмена

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

Не так уж и сложно, правда? Я бы даже сказал, что это гениально. Но так как нет механизма для загрузки действий пользователя прямо в Metamask для этих двух действий, нам приходится импровизировать. Вот где начинается самое интересное.

Как мы подойдем к этой проблеме

Во-первых, мы должны заметить сходство между этими двумя транзакциями. Один и тот же одноразовый номер, один и тот же адрес отправителя, и только с помощью этих двух свойств мы можем однозначно отличить транзакцию, идущую с адреса.

Во-вторых, мы должны посмотреть, что нам понадобится, чтобы иметь возможность сказать, что транзакция была подтверждена. Это хэш транзакции (txHash). Вот и все! Подробный механизм будет обсуждаться в следующих разделах с кодом в качестве примера.

Реализация JavaScript

1. Интерфейс

Мы сделаем это так. Во внешнем интерфейсе, после того как мы создадим транзакцию, мы просто получим информацию о транзакции, такую ​​как txHash, nonce, from, to и т. д., и отправим ее на наш сервер.

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

2. Бэкенд

Backend сделает тяжелую работу здесь. Давайте начнем с простой экспресс-конечной точки, которая будет отвечать за получение txInfo.

TxToWatch — это просто объект JavaScript. Я выбрал его, а не массив, потому что в этом случае им легче управлять. Нам нужны 3 вещи, чтобы иметь возможность различать транзакции:

  1. С адреса,
  2. одноразовый,
  3. Хэши транзакций.

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

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

Вы можете инициализировать его, как указано выше. Возьмите идентификатор проекта из Infura и создайте переменную с этим именем в коде.

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

К счастью, есть событие, на которое мы можем подписаться и которое выведет нам список всех ожидающих транзакций, т.е. операции, которые еще не были подтверждены. Бинго! После получения информации об ожидающих транзакциях, чтобы определить, была ли транзакция отправлена ​​или нет, мы должны отслеживать информацию blockNumber и blockHash. Если для них установлено значение null, это означает, что они еще не подтверждены. Наличие blockNumber и blockHash означает, что транзакция была включена в блок и подтверждена.

Если мы возьмем мое объяснение из предыдущего абзаца, оно будет переведено в код, который вы видите выше. Для каждой ожидающей транзакции (под ожидающей транзакцией лучше просто визуализировать ее как неподтвержденную, т.е. вы не знаете, была ли она включена в блок или нет) мы запускаем событие подписки, которое возвращает нам Хэш транзакции, который мы можем использовать для получения информации о транзакции. Затем мы проверяем наличие номера блока, и если мы его нашли, мы устанавливаем параметр успеха в значение true в массиве txToWatch.

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

Вот почему я также создал сниффер txToWatch, т. е. перебирающий транзакцию txToWatch и проверяющий хэш каждой транзакции, который у вас есть.

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

Проверка результата транзакции

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

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

Удачного кодирования!