Обработка жетонов
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Лучшие практики обработки жетонов
Жетоны - это токены в блокчейне TON - их можно рассматривать аналогично токенам ERC-20 в сети Ethereum.
Транзакции в TON становятся необратимыми уже после одного подтверждения. Для лучшего пользовательского опыта (UX/UI) рекомендуется избегать дополнительного ожидания.
Вывод средств
Highload Wallet v3 - это новейшее решение блокчейна TON, которое является золотым стандартом для вывода жетонов. Он позволяет вам воспользоваться преимуществами пакетной отправки средств.
Пакетное снятие средств - означает, что несколько переводов отправляются пакетами, что обеспечивает быстрый и дешевый вывод средств.
Зачислени я
Рекомендуется настроить несколько кошельков пополнения MEMO для улучшения производительности.
Пополнения с Memo - позволяет вам иметь один кошелек пополнения, и пользователи добавляют Memo, чтобы быть идентифицированными вашей системой. Это означает, что вам не нужно сканировать весь блокчейн, но это немного менее удобно для пользователей.
Пополнения без Memo - Это решение также существует, но его интеграция более сложна. Однако мы можем помочь вам с этим, если вы предпочтете выбрать этот путь. Пожалуйста, уведомите нас до того, как решите реализовать этот подход.
До полнительная информация
Ожидается, что каждый сервис в Экосистеме установит forward_ton_amount
равный 0,000000001 TON (1 нанотон), когда будет производиться вывод жетонов, чтобы отправить Jetton Notify при успешном переводе, иначе перевод не будет соответствовать стандарту и не сможет быть обработан другими CEX и сервисами.
-
Пожалуйста, найдите пример JS lib - tonweb - это официальная JS библиотека от TON Foundation.
-
Если Вы хотите использовать Java, Вы можете заглянуть в ton4j.
-
Для Go следует рассмотреть tonutils-go. На данный момент мы рекомендуем JS lib.
Оглавление
В следующих документах представлены подробные сведения об архитектуре жетонов в целом, а также основные концепции TON, которые могут отличаться от EVM-подобных и других блокчейнов. Это крайне важно, чтобы получить хорошее понимание TON, и оно значительно поможет вам.
В этом документе описано следующее по порядку:
- Общие сведения
- Архитектура
- Контракт Jetton Master (Выпуск токенов)
- Ко нтракт Jetton Wallet (кошелек пользователя)
- Макеты сообщений
- Обработка жетонов (off-chain)
- Обработка жетонов (on-chain)
- Обработка кошелька
- Лучшие практики
Общие сведения
Транзакции TON необратимы после одного подтверждения. Для ясного понимания читатель должен быть знаком с основными принципами обработки активов, описанными в этом разделе нашей документации. В частности, важно знать контракты, кошельки, сообщения и процесс развертывания.
Для лучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после того, как транзакции будут завершены в блокчейне TON. Подробнее можно прочитать в Catchain.pdf.
Быстрый переход к основному описанию обработки Jetton:
Централизованная обработка
On-Chain обработка
Блокчейн TON и лежащая в его основе экосистема классифицируют взаимозаменяемые токены (FT) как жетоны. Поскольку в блокчейне применяется шардинг, наша реализация взаимозаменяемых токенов уникальна по сравнению с аналогичными моделями блокчейнов.
В этом анализе мы более подробно рассмотрим формальные стандарты, описывающи поведение и метаданные жетонов. Менее формальный обзор архитектуры жетонов, ориентированный на шардинг, можно найти в нашем блоге "anatomy of jettons".
Мы также предоставили конкретные подробности, обсуждая наш процессор платежей TON с открытым исходным кодом (bicycle), который позволяет пользователям вносить и выводить как Toncoin, так и жетоны, используя отдельный адрес депозита без использования текстового поля memo.
Архитектура Jetton
Стандартизированные токены в TON реализованы с использованием набора смарт-контрактов, включая:
- Смарт-контракт Jetton master
- Смарт-контракт Jetton wallet


Смарт-контракт Jetton master
Смарт-контракт jetton master хранит общую информацию о жетоне (включая общее предложение, ссылку на метаданные или сами метаданные).
Jetton с symbol
==TON
или те, которые содержат системные уведомления, такие как: ERROR, SYSTEM и другие. Обязательно проверьте, отображаются ли жетоны в вашем интерфейсе таким образом, чтобы их нельзя было смешивать с переводами TON, системными уведомлениями и т. д. Иногда даже symbol
, name
и image
созданы таким образом, чтобы выглядеть почти одинаково с оригиналом с целью обмана пользователей.
Чтобы исключить возможность мошенничества для пользователей TON, пожалуйста, найдите оригинальный адрес жетона (Смарт-контракт Jetton master) для определенных типов жетонов или перейдите на официальный канал или веб-сайт проекта в социальных сетях для получения правильной информации. Проверяйте активы, чтобы исключить возможность мошенничества с помощью списка Tonkeeper ton-assets.
Получение данных о жетоне
Для извлечения более конкретных данных жетона используйте get метод контракта get_jetton_data()
.
Этот метод возвращает следующие данные:
Имя | Тип | Описание |
---|---|---|
total_supply | int | общее количество выпущенных жетонов, измеренное в неделимых ед иницах. |
mintable | int | информация о возможности чеканки новых жетонов. Это значение равно -1 (можно чеканить) или 0 (нельзя чеканить). |
admin_address | slice | |
jetton_content | cell | данные в соответствии с TEP-64, см. страницу анализа метаданных жетона для получения дополнительной информации. |
jetton_wallet_code | cell |
Также можно использовать метод /jetton/masters
из Toncenter API для получения уже декодированных данных и метаданных жетона. Мы также разработали методы для (js) tonweb и (js) ton-core/ton, (go) tongo и (go) tonutils-go, (python) pytonlib и многих других SDK.
Пример использования Tonweb для запуска метода get и получения url для метаданных off-chain:
import TonWeb from "tonweb";
const tonweb = new TonWeb();
const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: "<JETTON_MASTER_ADDRESS>"});
const data = await jettonMinter.getJettonData();
console.log('Total supply:', data.totalSupply.toString());
console.log('URI to off-chain metadata:', data.jettonContentUri);
Jetton minter
Как упоминалось ранее, жетоны могут быть либо выпускаемыми mintable
, либо не выпускаемыми non-mintable
.
Если они не выпускаемые, логика становится простой — нет способа чеканить дополнительные токены. Чтобы чеканить жетоны в первый раз, обратитесь к странице выпуск своего первого жетона.
Если жетоны выпускаемые, в minter contract есть специальная функция для чеканки дополнительных жетонов. Эту функцию можно вызвать, отправив внутреннее сообщение со специальным opcode с адреса администратора.
Если администратор жетона хочет ограничить их выпуск, есть три способа сделать это:
- Если вы не можете или не хотите обновлять код контракта, администратор должен передать право собственности с текущего администратора на нулевой адрес. Это оставит контракт без действующего администратора, таким образом, не давая никому возможности чеканить жетоны. Однако это также предотвратит любые изменения метаданных жетона.
- Если у вас есть доступ к исходному коду и вы можете его изменить, вы можете создать метод в контракте, который устанавливает флаг для прерывания любого процесса чеканки пос ле его вызова, и добавит инструкцию для проверки этого флага в функции выпуска.
- Если вы можете обновлять код контракта, вы можете добавить ограничения, обновив код уже развернутого контракта.
Смарт-контракт Jetton wallet
Контракты Jetton wallet
используются для отправки, получения и сжигания жетонов. Каждый контракт jetton wallet хранит информацию о балансе кошелька для определенных пользователей.
В некоторых случаях jetton wallet используются отдельно для каждого владельца жетона для каждого его типа.
Jetton wallets
не следует путать с кошельками, предназначенными для взаимодействия с блокчейном и хранящих только актива Toncoin (например, кошельки v3R2, highload кошельки и т.д.), которые отвечают за поддержку и управление только определенным типом жетонов.
Развертывание Jetton Wallet
При передаче жетонов
между кошельками транзакции (сообщения) требуют определенного количества TON в качестве оплаты сетевых комиссий за газ и выполнения действий согласно коду контракта Jetton wallet.
Это означает, что получателю не нужно развертывать Jetton wallet перед получением жетонов. Jetton wallet получателя будет развернут автоматически, если отправитель имеет достаточно TON в кошельке для оплаты необходимых комиссий за газ.
Получение адреса Jetton wallet для конкретного пользователя
Для получения jetton wallet
address
с помощью owner address
(адрес кошелька TON), Jetton master contract
предоставляет get метод get_wallet_address(slice owner_address)
.
- API
- js
Запустите
get_wallet_address(slice owner_address)
через метод/runGetMethod
из Toncenter API. В реальных случаях (не в тестовых) важно всегда проверять, что кошелек действительно принадлежит нужному Jetton Master. Подроднее смотрите пример кода.
import TonWeb from 'tonweb';
const tonweb = new TonWeb();
const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, { address: '<JETTON_MASTER_ADDRESS>' });
const jettonWalletAddress = await jettonMinter.getJettonWalletAddress(new TonWeb.utils.Address('<OWNER_WALLET_ADDRESS>'));
// It is important to always check that wallet indeed is attributed to desired Jetton Master:
const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, {
address: jettonWalletAddress
});
const jettonData = await jettonWallet.getData();
if (jettonData.jettonMinterAddress.toString(false) !== jettonMinter.address.toString(false)) {
throw new Error('jetton minter address from jetton wallet doesnt match config');
}
console.log('Jetton wallet address:', jettonWalletAddress.toString(true, true, true));
Дополнительные примеры можно найти в TON Cookbook.
Получение данных для определенного Jetton wallet
Чтобы получить баланс кошелька, данные об владельце и другую информацию, связанную с конкретным контрактом jetton wallet, используйте get метод get_wallet_data()
в контракте jetton wallet.
Этот метод возвращает следующие данные:
Имя | Тип |
---|---|
balance | int |
owner | slice |
jetton | slice |
jetton_wallet_code | cell |
- API
- js
Используйте get метод
/jetton/wallets
из API Toncenter для получения ранее декодированных данных jetton wallet.
import TonWeb from "tonweb";
const tonweb = new TonWeb();
const walletAddress = "EQBYc3DSi36qur7-DLDYd-AmRRb4-zk6VkzX0etv5Pa-Bq4Y";
const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider,{address: walletAddress});
const data = await jettonWallet.getData();
console.log('Jetton balance:', data.balance.toString());
console.log('Jetton owner address:', data.ownerAddress.toString(true, true, true));
// It is important to always check that Jetton Master indeed recognize wallet
const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: data.jettonMinterAddress.toString(false)});
const expectedJettonWalletAddress = await jettonMinter.getJettonWalletAddress(data.ownerAddress.toString(false));
if (expectedJettonWalletAddress.toString(false) !== new TonWeb.utils.Address(walletAddress).toString(false)) {
throw new Error('jetton minter does not recognize the wallet');
}
console.log('Jetton master address:', data.jettonMinterAddress.toString(true, true, true));
Макеты сообщений
Подробнее о сообщениях читайте здесь.
Обмен между Jetton wallet и кошельками TON происходит через следующую последовательность сообщений:


Сообщение 0
Sender -> sender's jetton wallet
. Сообщение о передаче содержит следующие данные:
Имя | Тип | Описание |
---|---|---|
query_id | uint64 | Позволяет приложениям связывать три типа сообщений Transfer , Transfer notification и Excesses друг с другом. Для корректного выполнения этого процесса рекомендуется всегда использовать уникальный query id запроса. |
amount | coins | Общая сумма ton coin , которая будет отправлена с сообщением. |
destination | address | Адрес нового владельца жетона |
response_destination | address | Адрес кошелька, используемый для возврата оставшихся ton coin с сообщением об излишках. |
custom_payload | maybe cell | Размер всегда >= 1 бит. Пользовательские данные (которые используются как отправителем, так и получателем jetton wallet для внутренней логики). |
forward_ton_amount | coins | Должно быть > 0, если вы хотите отправить transfer notification с forward payload . Это часть значения amount и должно быть меньше чем amount |
forward_payload | maybe cell | Размер всегда >= 1 бит. Если первые 32 бита = 0x0, это простое сообщение. |
Сообщение 2'
payee's jetton wallet -> payee
. Сообщение с уведомлением о переводе. Отправляется только если forward_ton_amount
не равен нулю. Содержит следующие данные:
Имя | Тип |
---|---|
query_id | uint64 |
amount | coins |
sender | address |
forward_payload | cell |
Здесь адрес sender
- это адрес Jetton wallet
Алисы.
Сообщение 2''
payee's jetton wallet -> Sender
. Тело сообщения. Отправляется только в том случае, если после уплаты комиссий остались какие-либо монеты ton. Содержит следующие данные:
Имя | Тип |
---|---|
query_id | uint64 |
Подробное описание полей контракта jetton wallet можно найти в интерфейсе описании стандарта жетона
TEP-74.
Как отправлять переводы жетонов с комментариями и уведомлениями
Для отправки транзакции требуется определенное количество ton coins для оплаты комиссии и сообщения об уведомлении.
Чтобы отправить комментарий, вам нужно настроить forward payload
. Установите первые 32 бита на 0x0 и добавьте свой текст, forward payload
отправляется во внутреннем сообщении jetton notify 0x7362d09c
. Оно будет сгенерировано только в том случае, если forward_ton_amount
> 0.
Рекомендуемое forward_ton_amount
для перевода жетонов с комментарием составляет 1 nanoton.
В конце концов, чтобы получить Excess 0xd53276db
сообщение, необходимо настроить response destination
.
Иногда при отправке жетонов может возникнуть ошибка 709
. Эта ошибка указывает на то, что количество Toncoin, прикрепленное к сообщению, недостаточно для его отправки. Убедитесь, что Toncoin > to_nano(TRANSFER_CONSUMPTION) + forward_ton_amount
, что обычно >0,04, если только forward payload не очень большая. Комиссия зависит от различных факторов, включая детали Jetton code и необходимость развертывания нового Jetton wallet для получателя.
Рекомендуется добавить к сообщению запас Toncoin и указать свой адрес в качестве response_destination
для извлечения сообщения Excess 0xd53276db
. Например, вы можете добавить 0,05 TON к сообщению, установив forward_ton_amount
в размере 1 nanoton (это количество TON будет прикреплено к сообщению jetton notify
0x7362d09c).
Вы также можете столкнуться с ошибкой cskip_no_gas
, которая указывает на то, что жетоны были успешно переведены, но никаких других вычислений не было выполнено. Это распространенная ситуация, когда значение forward_ton_amount
равно 1 nanoton.
Проверьте лучшие практики на примере "отправки жетонов с комментариями".
Обработка жетонов off-chain
Транзакции TON необратимы после одного подтверждения. Для лучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций в блокчейне TON. Подробнее читайте в Catchain.pdf.
Есть два способа получить жетоны:
- в централизованном горячем кошельке.
- используя кошелек с отдельным адресом для каждого отдельного пользователя.
В целях безопасности предпочтительнее иметь отдельные горячие кошельки для отдельных жетонов (несколько кошельков для каждого типа актива).
При обработке средств также рекомендуется иметь холодный кошелек для хранения избыточных средств, которые не участвуют в процессах автоматического депозита и вывода.
Добавление новых жетонов для обработки активов и первичной проверки
- Найдите правильный адрес смарт-контракта.
- Получите метаданные.
- Проверьте на мошенничество.
Идентификация неизвестного жетона при получении уведомления о переводе
Если в вашем кошельке получено уведомление о переводе неизвестного жетона, то ваш кошелек был создан для хранения определенного жетона.
Адрес отправителя внутреннего сообщения, содержащего тело Transfer notification
, является адресом Jetton wallet. Его не следует путать с полем sender
в теле Transfer notification
.
- Получите адрес Jetton master для нового Jetton wallet, получив данные кошелька.
- Получите адрес Jetton wallet для вашего адреса кошелька (как владельца), используя контракт Jetton master: Как получить адрес Jetton wallet для данного пользователя
- Сравните адрес, возвращенный master контрактом, и фактический адрес токена кошелька. Если они совпадают, это идеальный вариант. Если нет, то вы, вероятно, получили мошеннический токен, который является поддельным.
- Получите метаданные жетона: Как получить метаданные жетона.
- Проверьте поля
symbol
иname
на наличие признаков мошенничества. При необходимости предупредите пользователя. Добавление нового жетона для обработки и первичных проверок..
Прием жетонов от пользователей через централизованный кошелек
Чтобы предотвратить затор во входящих транзакциях на один кошелек, предлагается принимать депозиты через несколько кошельков и расширять количество этих кошельков по мере необходимости.
Ожидается, что каждый сервис в экосистеме установит forward_ton_amount
на 0,000000001 TON (1 nanoton) при выводе жетона, чтобы отправить Jetton Notify при успешном переводе, в противном случае перевод не будет соответствовать стандарту и не сможет быть обработан другими CEX и сервисами.
В этом сценарии платежный сервис создает уникальный идентификатор memo для каждого отправителя, раскрывая адрес централизованного кошелька и отправляемые суммы. Отправитель отправляет токены на указанный централизованный адрес с обязательным memo в комментарии.
Преимущества этого метода: Этот метод очень прост, поскольку при получении токенов не взимается никаких дополнительных комиссий, и они поступают непосредственно в горячий кошелек.
Недостатки этого метода: этот метод требует, чтобы все пользователи добавляли комментарий к переводу, что может привести к большему количеству ошибок при депозите (забытые memo, неправильные memo и т. д.), что означает большую нагрузку на службу поддержки.
Примеры с использованием Tonweb:
Подготовка
- Составьте список принимаемых жетонов (адреса Jetton master).
- Разверните горячий кошелек (используя v3R2, если не ожидается вывод жетонов; highload v3 - если ожидается вывод). Разверните кошелек.
- Выполните тестовый перевод жетонов, используя адрес горячего кошелька для его инициализации.
Обработка входящих жетонов
- Загрузите список принимаемых жетонов.
- Извлеките адрес Jetton wallet для развернутого горячего кошелька.
- Извлеките адрес Jetton master для каждого Jetton wallet, используя полученные данные кошелька.
- Сравните адреса контракта Jetton master из шага 1 и шага 3 (непосредственно выше). Если адреса не совпадают, необходимо сообщить об ошибке проверки адреса жетона.
- Извлеките список последних необработанных транзакций, с помощью учетной записи горячего кошелька и пройдитесь по нему (проверив каждую транзакцию отдельно). См: Проверка транзакций контракта.
- Проверьте входящее сообщение (in_msg) на предмет транзакций и извлеките исходный адрес из входящего сообщения. Пример Tonweb
- Если исходный адрес совпадает с адресом Jetton wallet, то необходимо продолжить обработку транзакции. Если нет, то пропустите обработку и проверьте следующую транзакцию.
- Убедитесь, что тело сообщения не пусто и первые 32 бита сообщения совпадают с op code
transfer notification
0x7362d09c
. Пример с использованием Tonweb. Если тело сообщения пустое или op code недействителен - пропустите транзакцию. - Прочитайте другие данные тела сообщения, включая
query_id
,amount
,sender
,forward_payload
. Макеты сообщений контрактов жетона, Пример с использованием Tonweb - Попытайтесь извлечь текстовые комментарии из данных
forward_payload
. Первые 32 бита должны совпадать с op code0x000000
, а остальные - с текстом в UTF-8 кодировке. Пример с использованием Tonweb - Если данные
forward_payload
пусты или op code недействителен - пропустите транзакцию. - Сравните полученный комментарий с сохраненными memo. Если есть совпадение (идентификация пользователя всегда возможна) - отправьте депозит.
- Начните заново с шага 5 и повторяйте процесс, пока не пройдете весь список транзакций.
Прием жетонов с адресов депозитов пользователей
Чтобы принимать жетоны с адресов депозитов пользователей, необходимо, чтобы платежный сервис создавал свой собственный индивидуальный адрес (депозит) для каждого участника, отправляющего средства. В этом случае требуется выполнение нескольких параллельных процессов, включая создание новых депозитов, сканирование блоков на наличие транзакций, вывод средств с депозитов на горячий кошелек и т. д.
Поскольку горячий кошелек может использовать один Jetton wallet для каждого типа жетона, необходимо создать несколько кошельков для инициирования депозитов. Чтобы создать большое количество кошельков, но при этом управлять ими с помощью одной seed-фразы (или закрытого ключа), необходимо указать другой subwallet_id
при их создании. В TON поддерживается функциональность для создания субкошельков версий v3 и выше.
Создание субкошелька в Tonweb
const WalletClass = tonweb.wallet.all['v3R2'];
const wallet = new WalletClass(tonweb.provider, {
publicKey: keyPair.publicKey,
wc: 0,
walletId: <SUBWALLET_ID>,
});
Подготовка
- Подготовьте список принимаемых жетонов.
- Разверните горячий кошелек (используя v3R2, если не ожидается вывод жетонов; highload v3 - если ожидается вывод жетонов). Разверните кошелек.
Создание депозитов
- Примите запрос на создание нового депозита для пользователя.
- Сгенерируйте новый адрес субкошелька (/v3R2) на основе seed-фразы горячего кошелька. Создание субкошелька в Tonweb
- Принимающий адрес может быть предоставлен пользователю как адрес, используемый для депозитов жетонов (это адрес владельца депозитного Jetton wallet). Инициализация кошелька не требуется, это можно сделать при выводе жетонов из депозита.
- Для этог о адреса необходимо рассчитать адрес кошелька Jetton через контракт Jetton master. Как получить адрес Jetton wallet для определенного пользователя.
- Добавьте адрес Jetton wallet в пул адресов для отслеживания транзакций и сохраните адрес субкошелька.
Обработка транзакций
Транзакции TON необратимы после одного подтверждения. Для лучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций в блокчейне TON. Подробнее читайте в Catchain.pdf.
Не всегда возможно определить точное количество жетонов, полученных из сообще ния, поскольку Jetton wallet не может отправлять сообщения transfer notification
, excesses
и internal transfer
. Они не стандартизированы. Это означает, что нет гарантии, что internal transfer
можно будет декодировать.
Поэтому для определения суммы, полученной в кошельке, необходимо запросить балансы с помощью get метода. Для получения ключевых данных при запросе балансов, блоки используются в соответствии с состоянием учетной записи для конкретного on-chain блока. Подготовка к принятию блока с помощью Tonweb.
Этот процесс выполняется следующим образом:
- Подготовьте прием блока (путем подготовки системы к принятию новых блоков).
- Получите новый блок и сохраните ID предыдущего блока.
- Получите транзакции из блоков.
- Отфильтруйте транзакции, используемые только с адресами из пула депозитного Jetton wallet.
- Декодируйте сообщения, используя тело
transfer notification
для получения более подробных данных, включая адресsender
,amount
жетонов и комментарий. (См.: Обработка входящих жетонов) - Если есть хотя бы одна транзакция с недекодируемыми исходящими сообщениями (тело сообщения не содержит op code для
transfer notification
и op code дляexcesses
) или без исходящих сообщений в учетной записи, то баланс жетонов должен быть запрошен с использованием get метода для текущего блока, в то время как предыдущий блок используется для расчета разницы в балансах. Теперь полный баланс депозита изменяется из-за транзакций, проведенных в рамках блока. - В качестве идентификатора для неопознанного перевода жетонов (без уведомления о переводе) могут использоваться данные транзакции, если присутствует одна такая транзакция или данные блока (если в блоке их присутствует несколько).
- Теперь необходимо проверить баланс депозита, чтобы убедиться, что он правильный. Если баланс депозита достаточен для инициирования перевода между горячим кошельком и существующем Jetton wallet, жетоны нужно вывести, чтобы гарантировать, что баланс кошелька уменьшился.
- Перезапустите с шага 2 и повторите весь процесс.
Вывод средств с депозитов
Переводы с депозита на горячий кошелек не следует делать с каждым пополнением депозита, поскольку за операцию перевода взимается комиссия в TON (оплачивается в виде сетевых сборов за газ). Важно определить ограниченную минимальную сумму жетонов, которое требуется для того, чтобы перевод (и, следовательно, депозит) был выгодным.
По умолчанию владельцы депозитных Jetton wallet не инициализируются. Это связано с тем, что нет предварительно установленного требования к оплате комиссии за хранение. Депозитные Jetton wallet могут быть развернуты при transfer
сообщений с телом перевода, которое затем может быть немедленно уничтожено. Для этого инженер должен использовать специальный механизм отправки сообщений: 128 + 32.
- Получите список депозитов, отмеченных для вывода на горячий кошелек
- Получите сохраненные адреса владельцев для каждого депозита
- Затем отправьте сообщения на каждый адрес владельца (путем объединения нескольки х таких сообщений в пакет) из highload кошелька с прикрепленной суммой TON Jetton. Это определяется путем сложения комиссий, используемых для инициализации кошелька v3R2 + комиссий за отправку сообщения с телом
transfer
+ произвольной суммы TON, связанной сforward_ton_amount
(если необходимо). Присоединенная сумма TON определяется путем сложения комиссий за инициализацию кошелька v3R2 (значение) + комиссий за отправку сообщения с теломtransfer
(значение) + произвольной суммы TON дляforward_ton_amount
(значение) (если необходимо). - Когда баланс на адресе станет ненулевым, статус аккаунта изменится. Подождите несколько секунд и проверьте статус аккаунта, он вскоре изменится с состояния
nonexists
наuninit
. - Для каждого адреса владельца (со статусом
uninit
) необходимо отправить внешнее сообщение с v3R2 кошелька init и body с сообщениемtransfer
для зачисления в Jetton wallet = 128 + 32. Дляtransfer
пользователь должен указать адрес горячего кошелька в качествеdestination
иresponse destination
. Можно добавить текстовый комментарий, чтобы упростить идентификацию перевода. - Проверьте доставку жетонов, исп ользуя адрес депозита на адрес горячего кошелька, учитывая обработку входящей информации о жетонах, которая представлена здесь.
Вывод жетонов
Ниже вы найдете пошаговое руководство по обработке вывода жетонов
Для вывода жетонов кошелек отправляет сообщения с телом transfer
на соответствующий Jetton wallet. Затем Jetton wallet отправляет жетоны получателю. Важно прикрепить некоторое количество TON (минимум 1 nanoTON) в качестве forward_ton_amount
(и необязательный комментарий к forward_payload
), чтобы вызвать transfer notification
. См.: Макеты сообщений контрактов жетонов
Подготовка
- Подготовьте список жетонов для вывода: Добавление новых жетонов для обработки и первичной проверки
- Инициируйте развертывание горячего кошелька. Рекомендуется использовать Highload v3. Развертывание кошелька
- Выполните перевод жетонов с использованием адреса горячего кошелька, чтобы инициализировать Jetton wallet и пополнить его баланс.
Обработка вывода средств
- Загрузите список обработанных жетонов
- Получите адреса Jetton wallet для развернутого горячего кошелька: Как извлечь адреса Jetton wallet для заданного пользователя
- Получите адреса Jetton master для каждого Jetton wallet: Как получить данные для Jetton wallet.
Требуется параметр
jetton
(который на самом деле является адресом контракта Jetton master). - Сравните адреса из контракта Jetton master из шага 1 и шага 3. Если адреса не совпадают, следует сообщить об ошибке проверки адреса жетона.
- Получите запрос на вывод, в которых фактически указывается тип жетона, переводимая сумма и адрес кошелька получателя.
- Проверьте баланс Jetton wallet, чтобы убедиться, что есть достаточно средств для выполнения вывода.
- Создайте сообщение.
- При использовании highload кошелька рекомендуется собирать пакет сообщений и отправлять по одному пакету за раз для оптимизации комиссий.
- Сохраните время истечения срока для исходящих внешних сообщений (это время, пока кошелек успешно не обработает сообщение, после этого кошелек больше не будет принимать сообщение)
- Отправьте одно сообщение или несколько сообщений (пакет сообщений).
- Получите список последних необработанных транзакций в учетной записи горячего кошелька и выполните его итерацию. Узнайте больше здесь: Проверка транзакций контракта, Пример Tonweb или используйте метод Toncenter API
/getTransactions
. - Просмотрите исходящие сообщения в аккаунте.
- Если существует сообщение с op code
transfer
, то его следует декодировать для получения значенияquery_id
. Полученныеquery_id
необходимо пометить как успешно отправленные. - Если время, необходимое для обработки текущей сканированной транзакции, превышает время истечения срока действия, а исходящее сообщение с заданным
query_id
не найдено, то запрос следует (это необязательно) пометить как просроченный и безопасно отправить повторно. - Просмотрите входящие сообщения в аккаунте.
- Если существует сообщение, которое использует op code
Excess 0xd53276db
, сообщение должно быть декодировано, а значениеquery_id
должно быть извлечено. Найденныйquery_id
должен быть помечен как успешно доставленный. - Перейдите к шагу 5. Просроченные запросы, которые не были успешно отправлены, должны быть возвращены в список вывода.
Обработка жетонов on-chain
Обычно для приема и обработки жетонов обработчик сообщений, отвечающий за внутренние сообщения, использует op code op=0x7362d09c
.
Транзакции TON необратимы после всего лишь одного подтверждения. Для лучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций в блокчейне TON. Подробнее в Catchain.pdf.
Рекомендации по обработке on-chain
Ниже приведен список рекоменда ций
, которые необходимо учитывать при обработке жетонов on-chain:
- Идентифицируйте входящие жетоны по типу их кошелька, а не по их контракту Jetton master. Другими словами, ваш контракт должен взаимодействовать (получать и отправлять сообщения) с конкретным jetton wallet (не с каким-то незнакомым кошельком, использующим определенный Jetton master).
- При связывании Jetton Wallet и контракта Jetton Master проверьте, что это соединение является двунаправленным, когда кошелек распознает master контракт и наоборот. Например, если ваша система контрактов получает уведомление от jetton wallet (который считает свой MySuperJetton своим master контрактом), его информация о переводе должна быть отображена пользователю, прежде чем показывать
symbol
,name
иimage
контракта MySuperJetton, проверьте, что кошелек MySuperJetton использует правильную систему контрактов. В свою очередь, если вашей системе контрактов по какой-то причине необходимо отправлять жетоны с использованием MySuperJetton или контракта MySuperJetton master, проверьте, что кошелек X, как и кошелек, использует те же параметры контракта. Кроме того, перед отправкой з апросаtransfer
в X убедитесь, что он распознает MySuperJetton как master. - Истинная сила децентрализованных финансов (DeFi) основана на возможности накладывать протоколы друг на друга, как блоки Lego. Например, скажем, жетон A обменивается на жетон B, который, в свою очередь, затем используется в качестве кредитного плеча в протоколе кредитования (когда пользователь предоставляет ликвидность), который используется для покупки NFT ... и так далее. Поэтому подумайте, как контракт может обслуживать не только пользователей off-chain, но и субъектов on-chain, прикрепляя токенизированное значение к уведомлению о переводе, добавляя custom payload, которую можно отправить с уведомлением о переводе.
- Помните, что не все контракты следуют одним и тем же стандартам. К сожалению, некоторые жетоны могут быть враждебными (использующими векторы атак) и созданы исключительно для атак на ничего не подозревающих пользователей. В целях безопасности, если рассматриваемый протокол состоит из множества контрактов, не создавайте большое количество jetton wallet одного типа. В частности, не отправляйте жетоны внутри протокола между контрактом депозита, контрактом хранилища или контрактом аккаунта пользователя и т. д. Злоумышленники могут намеренно вмешиваться в логику контракта, подделывая уведомления о переводе, суммы жетонов или параметры payload. Уменьшите потенциальный потенциал атаки, используя только один кошелек в системе на жетон (для всех депозитов и снятий).
- Также часто бывает хорошей идеей создать субконтракты для каждого индивидуального жетона, чтобы снизить вероятность подмены адреса (например, когда сообщение о переводе отправляется на жетон B с использованием контракта, предназначенного для жетона A).
- Настоятельно рекомендуется работать с неделимыми единицами жетонов на уровне контракта. Логика с плавающей запятой обычно используется для улучшения пользовательского интерфейса (UI), и это не связано с численным учетом on-chain.
Чтобы узнать больше о безопасном программировании смарт-контрактов в FunC от CertiK, не стесняйтесь читать этот ресурс. Разработчикам рекомендуется обрабатывать все исключения смарт-контрактов, чтобы они никогда не пропускались во время разработки приложений.
Рекомендации по обработке Jetton wallet
Как правило, все процедуры проверки, используемые для обработки жетонов off-chain, подходят и для кошельков. Для обработки Jetton wallet наши самые важные рекомендации следующие:
- Когда кошелек получает уведомление о переводе от неизвестного jetton wallet, жизненно важно доверять jetton wallet и его master адресу, поскольку это может быть вредоносная подделка. Чтобы защитить себя, проверьте Jetton Master (главный контракт), используя предоставленный им адрес, чтобы убедиться, что ваши процессы проверки распознают jetton wallet как легитимный. После того, как вы доверяете кошельку и он будет проверен как легитимный, вы можете разрешить ему доступ к остаткам на вашем аккаунте и другим данным в кошельке. Если Jetton Master не распознает этот кошелек, рекомендуется вообще не инициировать и не раскрывать ваши переводы жетонов и показывать только входящие переводы TON (Toncoin, прикрепленные к уведомлениям о переводах).
- На практике, если пользователь хочет взаимодействовать с жетоном, а не с jetton wallet. Другими словами, пользователи отправляют wTON/oUSDT/jUSDT, jUSDC, jDAI вместо EQAjN.../EQBLE... и т. д. Часто это означает, что когда пользователь инициирует пе ревод жетонов, кошелек спрашивает у соответствующего jetton master, какой jetton wallet (принадлежащий пользователю) должен инициировать запрос на перевод. Важно никогда не доверять слепо этим данным от Master (главного контракта) контракта. Перед отправкой запроса на перевод в jetton wallet всегда проверяйте, действительно ли jetton wallet принадлежит Jetton Master, которому он, как он утверждает, принадлежит.
- Помните, что недружественные Jetton Masters/jetton wallets могут со временем менять свои wallets/Masters. Поэтому крайне важно, чтобы пользователи проявляли должную осмотрительность и проверяли легитимность любых кошельков, с которыми они взаимодействуют, перед каждым использованием.
- Всегда проверяйте, что вы отображаете жетоны в своем интерфейсе таким образом, чтобы они не смешивались с переводами TON, системными уведомлениями и т. д. Даже параметры
symbol
,name
иimage
могут быть созданы, чтобы вводить пользователей в заблуждение, делая пострадавших потенциальными жертвами мошенничества. Было несколько случаев, когда вредоносные жетоны использовались для имитации переводов TON, ошибок уведомлений, вознаграждений или объявлений о заморозке активов. - Всегда будьте начеку в отношении потенциальных злоумышленников, которые создают поддельные жетоны, хорошей идеей будет предоставить пользователям функциональные возможности, необходимые для исключения нежелательных жетонов в их основном пользовательском интерфейсе.
Авторы: kosrk, krigga, EmelyanenkoK и tolya-yanot.
Лучшие практики
Если вы хотите готовые тестовые примеры, проверьте SDKs и попробуйте их запустить. Ниже приведены фрагменты кода, которые помогут вам понять обработку жетонов с помощью примеров кода.