📚Чтение заметок
Как мы уже упоминали в нашем 1-м уроке этой главы, TON имеет быстро растущий набор инструментов программирования, и иногда нет смысла создавать свою собственную локальную настройку. Есть отличный, который стоит упомянуть, который поддерживается командой TonTech, официально поддерживаемой Фондом TON - Blueprint.
Процесс развертывания также очень упрощен в Blueprint. Однако мы собираемся создать наш пользовательский сценарий развертывания, чтобы лучше понять логику, стоящую за ним.
Мы на финише! Поверьте мне, если вы зашли так далеко - я более чем уверен, что вы станете разработчиком контрактов TON. Для меня большая честь быть тем, кто на борту вас в этом процессе!
До сих пор мы создали наши компиляции и тестовые костюмы, но так же, как stallites должны быть в космосе - смарт-контракты должны быть в цепочке. Давай сделаем это!
Работа с тестовой сетью
Вы уже слышали о testnet, которая представляет собой отдельную сеть, предназначенную для тестирования всех возможных вещей для разработчиков.
Testnet работает с тестовыми монетами TON. Они не стоят реальной стоимости, поэтому вам не нужно их покупать. Вы можете легко получить их от официального testnet giver Telegram bot.Первоначально мы собираемся развернуть или заключить контракт с testnet.
Этот бот спросит у вас ваш адрес, поэтому вам нужен кошелек, который будет работать с тестовыми монетами TON. Вы, вероятно, знакомы с такими кошельками, как Tonhub и Tonkeeper. Tonkeeper и Tonhub имеют встроенную функциональность тестовой сети. Вы можете использовать как Tonhub, так и Tonkeeper, но, например, я буду использовать кошелек Tonhub, сделанный командой TonWhales. Он доступен для обоих iOS and Android. Перейдите по одной из ссылок и загрузите ее на свой мобильный телефон.
После установки Tonhub нажмите примерно 7 раз на номер версии приложения на последней вкладке нижнего меню со значком Gear под названием "Еще". Затем нажмите на селектор сети и переключите сеть в тестовую сеть. Теперь вернитесь на вкладку "Главная" и скопируйте и адрес вашего кошелька для монет TON - используйте его адрес для получения монет тестовой сети на testnet giver Telegram bot.
Развернуть скрипт
Теперь давайте создадим новый файл в нашей папке скриптов - deploy.ts. Как вы помните, для развертывания контракта нам нужно:
- Рассчитать будущий адрес контракта
- Составить исходное состояние контракта (код и первоначальные данные)
- Сочините сообщение, которое будет иметь исходное состояние
- Отправьте составленное сообщение на будущие адреса контракта на блокчейне
Вот как выглядит наш сценарий развертывания, прежде чем мы действительно отправим сообщение о развертывании:
Позвольте мне подробнее рассказать о том, что происходит в этих строках:
const stateInit: StateInit = {
code: codeCell,
data: dataCell,
};
const stateInitBuilder = beginCell();
storeStateInit(stateInit)(stateInitBuilder);
const stateInitCell = stateInitBuilder.endCell();
Важной концепцией, которая здесь используется, является Builder. Вам нужно будет понять это, чтобы успешно создавать контракты FunC и управлять ими с помощью TypeScript. Как вы можете видеть в коде, мы используем функцию beginCell, которая возвращает нам Builder (вы можете увидеть это, если навести курсор на stateInitBuildervariable и проверить его тип).
Мы передаем stateInit в storeStateInit - это дает нам функцию, которая готова записать предоставленный StateInit в конструктор. Мы немедленно выполняем эту функцию и передаем конструктор, который мы создали на предыдущем шаге.
На данный момент у нас уже есть конструктор, в котором уже записаны желаемые данные InitState. Все, что нам нужно сделать, это запустить функцию .endCell(), и она завершит конструктор в готовую ячейку с StateInit.
Мы могли бы достичь того же результата, построив такую ячейку вручную. Вот код:
const stateInitCell = beginCell()
.storeBit(false) // split_depth - Parameter for the highload contracts, defines behaviour of splitting into multiple instances in different shards. Currently StateInit used without it.
.storeBit(false) // special - Used for invoking smart contracts in every new block of the blockchain.
Available only in the masterchain. Regular user's contracts used without it.
.storeMaybeRef(codeCell) // code - Contract's serialized code. .storeMaybeRef(dataCell) // data - Contract initial data.
.storeUint(0, 1) // library - Currently StateInit is used without libs
.endCell();
Тем не менее, это потребует от нас более глубокого понимания тела InitState. Вы можете прочитать больше об этом here in documentation.
Составление сообщения с помощью StateInit
IЧтобы отправить сообщение, нам понадобится кошелек Tonhub, который вы установили в начале этого урока. Tonhub имеет крутой API, который обеспечивает глубокую связь с кошельком, что означает, что мы можем составить ссылку, которая будет иметь все параметры, необходимые для отправки сообщения, а затем открыть эту ссылку в Tonhub и подписать фактическую транзакцию отправки сообщения. Для этого потребуется установка библиотеки qs, которая поможет нам составить URL-адрес со сложными параметрами.
Установите его, запустив:
yarn add qs @types/qs --dev
Поскольку наш кошелек Tonhub находится на мобильном телефоне, а ссылка на нашем рабочем столе - давайте просто сгенерируем qr-код этой ссылки и покажем его в терминале для сканирования с помощью Tonhub и отправки сообщения о развертывании. Для этих целей мы будем использовать библиотеку qrcode-terminal.
Установите его, запустив:
yarn add qrcode-terminal @types/qrcode-terminal --dev
With help of those two libraries, our deploy script is now looking like this:
Now our code will look like this:
И опять же, мы сразу же создаем еще один скрипт, выполняющий ярлык в нашем файле package.json. Давайте назовем этот скрипт deploy:testnet, чтобы позже мы могли использовать имя deploy для развертывания основной сети.:
{
... our previous package.json keys
"scripts": {
... previous scripts keys
"deploy:testnet": "yarn compile && ts-node ./scripts/deploy.ts" }
}
Давайте запустим сценарий развертывания (yarn deploy:testnet) и отсканируем QR-код с помощью мобильного приложения Tonhub. Убедитесь, что у вас есть монеты tesnet TON на этом кошельке в Tonhub.
Как мы проверим, что контракт успешно развернут? Легко! Вы, вероятно, уже знакомы с концепцией исследователей блокчейна. Одним из исследователей блокчейна в TON является Tonapi. У него также есть testnet version.
Откройте версию тестовой сети в своем браузере и вставьте адрес смарт-контракта в строку поиска. Это откроет страницу вашего смарт-контракта. Если вы сделали все со мной шаг за шагом - вы увидите одну транзакцию в 1 тонну, которая развернула наш контракт в блокчейне.
Поздравляем! Ваш первый смарт-контракт TON развернут!
Тест на цепочку после развертывания
Да, вы сделали это, но есть важная вещь, о которой вы действительно хотите позаботиться - тест после развертывания в цепочке. Как только наш контракт будет развернут, мы хотим убедиться, что функциональность ведет себя так, как мы ожидаем. Для этой цели мы напишем скрипт, который фактически проверит нашу функциональность.
Тем не менее, прежде чем запустить этот тест, мы должны убедиться, что наш контракт развернут. Для этого нам нужно получить доступ к текущему состоянию блокчейна TON. Существует отличный инструмент, который позволяет нам подключаться практически ко всем возможным типам API блокчейна TON - TON Access Собрано Orbs team.
onchaintest.ts irst things first - создайте файл в нашей папке скриптов.
Добавьте скрипт запуска ярлыка в файл package.json:
{
... our previous package.json keys
"scripts": {
... previous scripts keys
"onchaintest": "ts-node ./scripts/onchaintest.ts" }
}
Чтобы проверить, развернут ли контракт, нам нужен его адрес. Мы хотим, чтобы наша настройка была удобной в использовании и требовала минимальной ручной работы, поэтому мы не будем жестко кодировать адрес, который мы видели до развертывания. Мы собираемся рассчитать его независимо, потому что помним, что адрес может измениться в зависимости от кода контракта и его первоначальных данных о состоянии.
Вот как выглядит наш первоначальный код, когда мы хотим получить адрес нашего контракта:
import { Cell, contractAddress } from "ton";
import { hex } from "../build/main.compiled.json";
async function onchainTestScript() {
const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];
const dataCell = new Cell();
const address = contractAddress(0, {
code: codeCell,
data: dataCell,
});
}
onchainTestScript();
Давайте сначала установим @orbs-network/ton-access :
yarn add @orbs-network/ton-access --save
Теперь давайте обновим наш код с помощью логики проверки состояния нашего контракта в сети по его адресу:
Давайте еще немного погрузимся в этот код. Что у нас здесь есть?
Мы используем функцию getHttpV4Endpoint для подключения к конечной точке API, размещенной командой Orbs, и получить клиентский объект протокола v4. Вы можете узнать больше о протоколе v4 here
Пока что мы должны установить конфигурационный параметр сети на testnet.
- Мы получаем информацию о последнем блоке
- Мы используем метод getAccount клиента v4, предоставляя ему порядковый номер и наш контракт address
В результате мы можем остановить наш сценарий в случае, если контракт еще не был развернут.
Теперь давайте перейдем к фактическому тесту. Мы создадим ссылку для простой транзакции, которая отправит 1 TON на адрес нашего контракта. Так же, как и в процессе развертывания, мы покажем QR-код этой ссылки, чтобы вы могли отсканировать его с помощью мобильного приложения кошелька Tonhub.
Мы также должны импортировать функцию toNano из библиотеки @ton-core. Он конвертирует количество монет TON в нано. Один TON имеет 1 000 000 000 нано. В TON количество монет TON всегда представлено в нано. Для удобства использования большую часть времени мы будем работать с nanos в виде строки.
Кроме того, обратите внимание, что мы используем метод toString объекта адреса, предоставляя его конфигурационный параметр, который указывает, что адрес из тестовой сети.
Сразу после показа QR-кода наш скрипт начнет вызывать метод геттера в нашем контракте, чтобы получить последний адрес отправителя. Мы будем вести журнал консоли только в том случае, если изменится адрес последнего отправителя, чтобы избежать того, чтобы консоли регистрировать те же результаты.
Давайте сначала посмотрим код для этой логики получения последних отправителей, мы разберем, что там происходит, а затем интегрируем его в наш скрипт:
Что именно мы делаем в этом коде:
- Мы настраиваем эту функцию, чтобы она повторялась каждые 2 секунды
- Каждый раз, когда мы выполняем проверку, нам нужно получить порядковый номер последнего блока с помощью getLastBlock
- Мы используем runMethod для вызова нашего метода геттера, и параметры, которые нас интересуют, - exitCode и результат.
- Мы следим за тем, чтобы скрипт останавливался, если вызов не был успешным или полученные данные не являются фрагментом (как вы помните, адрес в TON всегда является фрагментом)
- Мы берем результат метода get, а именно его первый элемент (результат - массив, так как в других случаях может быть более одного результата, возвращаемого методом getter)
- Мы берем параметр ячейки результата, открываем его для разбора, а затем читаем из него адрес
- Мы сравниваем строковую версию адреса со строковой версией возможного предыдущего отправителя, который мы получили. Если они не равны - мы регистрируем новый последний адрес отправителя.
Давайте посмотрим, как выглядит наш окончательный код:
Давайте продолжим и запустим его!
yarn onchaintest
Если вы все сделали правильно, вы увидите QR-код в своем терминале и последний адрес отправителя. Он должен быть равен адресу вашего кошелька Tonhub, который вы использовали для развертывания контракта.
Когда мы развертывали контракт, мы отправили код и начальное состояние вместе с 1 TON, поэтому сразу после развертывания контракта его код был выполнен и сохранен отправителя в хранилище c4
TO убедитесь, что наш скрипт работает так, как ожидалось, вы можете создать еще один кошелек на Tonhub, заполнить его монетами тестовой сети TON и снова отправить его в наш контракт. Вы увидите обновление в консоли через несколько секунд, потому что последний адрес отправителя изменилсяd.
Развертывание в основной сети
Давайте скорректируем наш сценарий, чтобы мы могли развернуть контракт в основной сети.
Мы должны обновить наш код во всех местах, которые включают дифференциацию testnet/mainnet.
Давайте теперь обновим наш код файла deploy.ts:
We only had to change our code in one place:
- При регистрации адреса контракта мы устанавливаем флаг testOnly только в том случае, если мы в тестовой сети
Теперь давайте обновим наш скрипт onchaintest.ts тем же:
Нам пришлось также изменить две вещи в нашем скрипте onchaintest.ts:
- Когда мы подключаемся к клиенту для чтения блокчейна
- При регистрации адреса контракта мы устанавливаем флаг testOnly только тогда, когда мы в тестовой сети
Теперь мы можем развернуть и запустить тест onchain как в тестовой сети, так и в основной сети!
Имейте в виду, что для основной сети вам нужно вернуть свой кошелек TonHub в основную сеть. Он также доступен для iOS and Android.
Ты сделал это! Серьезно, я горжусь тобой!
Мы проделали солидный объем работы, но хорошо то, что теперь вы понимаете весь процесс разработки и развертывания контрактов.
В нашей следующей главе мы собираемся углубиться в более сложную логику FunC и написать для нее локальные тесты.