Wallet V5 Extension
Механизм расширений кошелька v5: разрешённые «помощники» (другие смарт-контракты), которые могут отправлять сообщения от имени кошелька. Основа gasless-переводов и подписок на TON.
Синонимы: w5-extension, w5 plugin, wallet v5 extension, w5 helper
Wallet V5 Extension — функция кошелька v5, появившаяся в 2024 году. Кошелёк хранит whitelist адресов-расширений; любой из них может слать internal-message «как будто от кошелька» без подписи владельца.
Use-cases
- Gasless USDT: relayer добавляется как extension, оплачивает газ, держит комиссию.
- Subscriptions: автоматическое списание в подписке без участия пользователя на каждой итерации.
- DApp-помощники: одобренный DApp может пакетно отправлять transactions от имени пользователя.
Безопасность
Extension == полный доступ к балансу. Whitelist менеджится только владельцем (signed-action). Любой добавленный extension может вывести все средства — добавляйте только проверенные сервисы. Перед approve в кошельке внимательно смотрите, какой адрес запрашивает права.
Отличия от Wallet V4 plugins
V4-плагины умели только subscription-cron, V5-extensions — произвольные внутренние сообщения. V4 фактически устарел после релиза V5, новые кошельки идут с W5 by default.
Storage-layout: где хранятся extensions
W5 держит whitelist в extensions — HashmapE 256 int1 в data-cell кошелька. Ключ — 256-битный хеш адреса (workchain + address hash), значение — флаг 1 (всегда true для записи присутствия). Чтение происходит так:
(int found, slice _) = extensions~udict_get?(256, ext_hash);
throw_unless(146, found); ; "Extension not whitelisted"
Размер записи ~265 бит → один extension стоит хранение ~$0.0001/год в forward-fees. Лимит на количество extensions нет, но на практике более 20 — редкость.
API установки и удаления
В TypeScript-клиенте @ton/ton (с поддержкой W5) операции выглядят так:
import { WalletContractV5R1 } from '@ton/ton';
const wallet = client.open(WalletContractV5R1.create({ publicKey, walletId }));
// Добавить extension
await wallet.sendAddExtension({
seqno: await wallet.getSeqno(),
secretKey,
extensionAddress: Address.parse('EQrelayer...'),
});
// Удалить
await wallet.sendRemoveExtension({
seqno: await wallet.getSeqno(),
secretKey,
extensionAddress: Address.parse('EQrelayer...'),
});
Обе операции требуют signed-action от владельца. Изнутри они кодируются как опкоды add_extension (0x02) / remove_extension (0x03) в формате action-list W5.
Что extension может и не может
| Операция | Может extension | Может signed-action |
|---|---|---|
| Отправлять internal-messages с send_mode 0/1/2/3 | ✅ | ✅ |
| Добавлять другие extensions | ❌ (по умолчанию) | ✅ |
| Удалять signing-key | ❌ | ✅ |
Менять is_signature_allowed (signed-mode lock) | ❌ | ✅ |
Делать set_data напрямую | ❌ | ❌ |
Это «гражданство второго класса» — extension не может превратиться в нового владельца, но может слить весь баланс одним сообщением. Различение важно при оценке риска.
Реальные кейсы 2024-2026
- Tonkeeper Battery — extension от Tonkeeper, оплачивает газ на jetton-переводы из баланса предоплаченного «battery»-токена.
- TONX Sponsor — provider gasless-USDT, добавляется как extension при первом переводе.
- Subscription-protocols — TonsClub, Subby (на 2026 в alpha) — extension с rate-limit’ом списания.
- Hot-wallet routing для бирж — биржа может добавить extension cold-wallet хранилища, и из cold через batch выходят transfers без подписи каждой operation.
Best-practice удаления
Если перестали пользоваться dApp с extension’ом — удалите его явно. Adapter-уязвимости в логике extension’а могут привести к попытке слива даже через год после последнего легитимного использования. Tonkeeper показывает список активных extensions в Settings → Wallet → Extensions; периодический аудит — 5 минут раз в квартал.
Связанные темы
- Wallet V5 — общий обзор W5-архитектуры.
- Gasless-перевод — основной use-case extensions.
- Internal message — что extension физически отправляет.