October 14

Wtf is sui

Я положил крышу, устал и решил, что писать статью по суи будет попроще, чем класть ещё и конёк.

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

С линукса я давно слез, а мака у меня никогда и не было

Во-вторых, вся дока на басурманском языке, который я хоть и знаю, но вдумчиво читать на нём реально влом.

В-третьих, когда я всё-таки поставил библу и начал более-менее разбираться я встречаю это

Так и не нашел решения этой проблемы, хотя казалось бы, я всего-то запускаю пример с оффициального гитхаба

В общем моё мнение о суи еще с прошлого года не изменилось и я начал ковырять палочкой это чудо.
Спустя пару дней я понял несколько очень важных вещей. Дальше всё будет на примере конкретного класса, а так же не будет возможности копировать код. Почему? Потому что нужно набивать руку печатать всё самому, а то привыкли, видите ли, с чатов гпт всё копировать.

Итак. Обратимся к офф доке и узнаем, что нам вообще нужно, чтобы отправить транзакцию:

Мы тут сразу видим какой-то конфиг, какой-то клиент. Все они дефолтные, судя по коду. Но что же будет если я скопирую этот код и запущу?

И он не может найти какой-то файл конфигурации. Что это за файл? Догадаться нужно самому, потому что в доке я этого не нашел. Поэтому после пары часов поисков, лазанья по всей библиотеке, метода научного тыка я обнаружил, что нужно создать 2 файла. Первый — это уже известный нам client.yaml, а второй — с произвольным названием, где по задумке разработчиков должны храниться все ключи от текущего конфига. С именем я не заморачивался и просто назвал a.sui

Теперь по содержанию файлов и что означает каждое поле

client.yaml

client.yaml представляет собой файлик, в котором хранятся данные по разным конфигам. Потом можно будет выбрать любой, но я использую один и програмно его изменяю.
keystore — В этом поле указывается расположение файла со всеми(или не совсем) приватными ключами. Название произвольно.
active_address — Это активный адрес текущего окружения. Принцип работы такой же, как и в метамаске. Если выбрать адрес, то он и будет подписывать(ЗЫ иметь приватный ключ от этого адреса не обязательно, оно и так запустится)
active_env — Тут указывается название текущего окружения
envs — Тут списком перечисляются разные окружения, у каждого свои параметры, такие как: alias - имя, rpc - ссылка на ноду, есть ещё парочка, но они не обязательны

a.sui

В файле a.sui, а именно так я назвал файл с ключами, обязан быть хотя бы один приватный ключ. Я выбрал первый, что подходит из интернета. В целом, если брать конкретно мой класс из примера, это ни на что не влияет.

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

Начнем с самого базового. Создадим класс и прикрутим функцию __init__

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

Дальше нам нужно создать конфиг и записать в него наш приватный ключ

Тут первой строкой мы создаем конфиг и указываем ему путь до файла конфигурации, дальше добавляем приватный ключ в него и выбираем нужную кривую(а их тут 4 штуки: ED25519, SECP256K1, SECP256R1, BLS12381).
После этого мы указываем в конфиге, что текущий активный адрес — это тот, что получился из нашего ключа.

Дальше мы создаём клиент, в него пихаем конфиг, и перезаписываем httpx клиент, чтобы он мог поддерживать прокси.

Для удобства я прикрутил ещё функцию/свойство для получения адреса от аккаунта. Целиком это выглядит так:

А теперь самое интересное. Как же отправлять транзакции? Всё очень просто.
Тут всё практически так же, как и в ЕВМ. Делаем транзу руками, смотрим на типы аргументов и их значения, пишем это в коде и вуаля, транза отправляется. Ну почти.

Буду брать в качестве примера транзакцию с movepump'a. А именно эту транзакцию

Если зайти по ссылке, то мы увидем много всякого непонятного, но нам всё и не нужно. Нам нужны вот эти 2 вещи

Если нажать на них, то они откроются и всё станет опять непонятно.

Split coin делает так, чтобы из одного объекта монеты получилось два. Допустим у нас был 1 суи. Мы вызвали split coins, указали, что мы это делаем с суи и вписали число 100000000( Оно же 0.1 SUI). После этого у нас в сканере в портфолио видим картину, где у нас 2 разных баланса суи, в одном больше монет, в другом меньше. Если брать конкретно этот пример, то будет 0.9 и 0.1(если округлять и не учитывать газ).

Перед тем, как показывать код, покажу нужные библиотеки

В коде это реализуется очень просто. Сначала мы создаем экземпляр транзакции, потом в нее засовываем Split Coins

GasCoin тут значит, что мы используем сам токен SUI

Дальше создаём саму транзакцию, если работали с аптосом, то всё будет очень просто.

В target указываем адрес контракта, модуль и функцию
В arguments аргументы с нужными типами данных
В type_arguments указываем уже кастомные типы из Move, которые может потребовать функция

В данном конкретном случае используется Nestedresult. Оно возвращает конкретное значение из конкретного вызова по счёту. 0 0 значит, что вернёт первое значение первого вызова, а у нас это 100000000.

Все типы данных есть в табличке в документации тут

Осталось только отправить транзакцию. Делаем так и всё

В gas_budget указываем максимальный газ, который готовы заплатить за транзакцию.

И Всё в целом
Если найдёте косяк в этой статье, то это был не я, а злой гном-хуекрад, который зашел с моего пк. Просьба оповестить о таких вещах в лс