# Подписание транзакций и ордеров в MetaMask
MetaMask — расширение браузера для хранения ключей аккаунта, управления криптоактивами и взаимодействия с децентрализованными приложениями.
Для поддержки MetaMask в протокол Waves добавлены:
- поддержка Ethereum-like транзакций,
- поддержка ордеров с подписью ECDSA в транзакции обмена.
В результате пользователям MetaMask стали доступны:
- перевод токенов в сети Waves — как системного токена WAVES, так и пользовательских;
- вызов dApp-скрипта в сети Waves;
- подписание биржевого ордера.
Разработчики приложений могут использовать библиотеку Signer совместно с ProviderMetamask для подписания и отправки транзакций от имени пользователя MetaMask.
Поддержка MetaMask не подразумевает взаимодействия с другими блокчейнами.
Поддержка MetaMask доступна c момента активации фичи № 17 “Ride V6, MetaMask support”.
# Адрес пользователя
Адрес пользователя MetaMask состоит из 20 байт. Адрес в формате Waves также содержит 20 значимых байт, к которым добавляется префикс, общий для всех адресов сети, и контрольная сумма (см. также раздел Бинарный формат адреса). Таким образом, адрес пользователя MetaMask можно преобразовать в формат Waves и наоборот: в основе лежат одни и те же 20 байт.
⚠️ Аккаунт, созданный в MetaMask, невозможно перенести в приложение-кошелек Waves (WX Network, Keeper Wallet или другой), а аккаунт из кошелька Waves невозможно перенести в MetaMask. MetaMask и Waves используют разные криптографические алгоритмы, поэтому из одной и той же seed-фразы получатся разные аккаунты с разными адресами. Не существует способа получить из seed-фразы MetaMask seed-фразу Waves, соответствующую тому же адресу, и наоборот.
В интерфейсах адрес пользователя MetaMask представлен в кодировке HEX, а адрес Waves — в base58. Для преобразования адреса из одного формата в другой можно использовать:
- Waves Explorer для Mainnet, Testnet и Stagenet.
- функции
wavesAddress2eth
,ethAddress2waves
библиотеки node-api-js.
# Подключение к сети Waves
Нода Waves предоставляет RPC API с поддержкой функций, необходимых для работы MetaMask.
Подключение MetaMask к сети Waves может быть выполнено пользователем самостоятельно или программно.
В случае самостоятельного подключения пользователь выбирает в списке сетей «Пользовательский RPC» и указывает параметры подключения:
- Имя сети — Waves, Waves Testnet или Waves Stagenet. Подробнее о сетях блокчейна
- URL RPC — адрес ноды Waves с открытым RPC API, например адрес пула публичных нод:
- для Mainnet:
https://nodes.wavesnodes.com/eth
- для Testnet:
https://nodes-testnet.wavesnodes.com/eth
- для Stagenet:
https://nodes-stagenet.wavesnodes.com/eth
- для Mainnet:
- Идентификатор цепочки (сети блокчейна): 87 для Mainnet, 84 для Testnet, 83 для Stagenet.
- Символ валюты — WAVES.
Для программного подключения веб-приложение может использовать библиотеку Signer совместно с ProviderMetamask:
- Приложение вызывает функцию
login()
. - Signer вызывает соответствующую функцию ProviderMetamask, а ProviderMetamask вызывает API MetaMask.
- MetaMask открывает окно, в котором пользователь подтверждает подключение к сети.
- Получив подтверждение, MetaMask добавляет подключение к сети, а также возвращает адрес пользователя.
В результате MetaMask отображает сеть Waves в качестве доступной, а функция login()
возвращает адрес пользователя в формате Waves.
Пример программного подключения см. в подразделе Примеры использования MetaMask ниже.
# Внесение токена
Пользователи кошельков Waves, таких как Keeper Wallet, WX Network, WavesFX и других (приложения разработаны сторонними командами из сообщества), могут перевести токены пользователю MetaMask. В некоторых кошельках поддерживаются только адреса в формате Waves, поэтому необходимо предварительно преобразовать адрес получателя из MetaMask-представления в Waves. В результате создается обычная транзакция перевода.
Баланс системного токена WAVES отображается в MetaMask автоматически, если подключена сеть Waves. Чтобы добавить отображение баланса по другому токену, нужно в качестве адреса контракта токена указать ID токена в MetaMask-представлении, а именно первые 20 байт идентификатора в кодировке HEX. Для преобразования ID токена из одного формата в другой можно использовать Waves Explorer для Mainnet, Testnet и Stagenet.
# Вызов скрипта
Веб-приложение может выполнить вызов dApp-скрипта от имени пользователя MetaMask, используя библиотеку Signer совместно с ProviderMetamask:
- Приложение формирует и отправляет транзакцию вызова скрипта c помощью функции
invoke({...}).broadcast()
. - Signer вызывает соответствующую функцию ProviderMetamask, а ProviderMetamask вызывает API MetaMask.
- MetaMask открывает окно, в котором пользователь может посмотреть детали транзакции, подтвердить или отклонить ее.
- Получив подтверждение от пользователя, MetaMask генерирует для транзакции подпись ECDSA и отправляет подписанную транзакцию на ноду Waves через RPC API.
- MetaMask отображает статус транзакции.
Примечания:
- MetaMask не поддерживает подписание транзакции без отправки ее на блокчейн, поэтому функцию
sign()
использовать не следует. - Нода Waves не поддерживает ускорение или отмену транзакции и обрабатывает только первоначальную транзакцию.
Пример вызова скрипта см. в подразделе Примеры использования MetaMask ниже.
# Перевод токена
Чтобы самостоятельно выполнить перевод токена из кошелька MetaMask, пользователю необходимо:
- Подключить сеть Waves (см. выше).
- Баланс системного токена WAVES отображается автоматически. Чтобы добавить отображение баланса по другому токену, нужно в качестве адреса контракта токена указать ID токена в MetaMask-представлении, а именно первые 20 байт идентификатора в кодировке HEX.
- Перевести токен на другой адрес. Адрес необходимо указать в MetaMask-представлении.
MetaMask формирует Ethereum-like транзакцию, подписывает ее закрытым ключом пользователя и передает на ноду Waves.
Для преобразования адреса получателя и ID токена в MetaMask-представление можно использовать Waves Explorer for Mainnet, Testnet, and Stagenet.
Веб-приложение может выполнить перевод любого токена в сети Waves от имени пользователя MetaMask, используя библиотеку Signer совместно с ProviderMetamask. Для этого приложение формирует и отправляет транзакцию перевода с помощью функции transfer({...}).broadcast()
. Дальнейшая обработка транзакции аналогична вызову скрипта, см. подраздел выше.
# Особенности Ethereum-like транзакции
- Транзакция не может быть отправлена со смарт-аккаунта или dApp, поскольку пользователю MetaMask доступны только перевод токена и вызов скрипта, а установка скрипта недоступна.
- Спонсирование комиссии недоступно: комиссия может быть указана только в WAVES.
См. также раздел Бинарный формат Ethereum-like транзакции.
# Поддержка в Ride
В случае вызова скрипта с помощью Ethereum-like транзакции структура Invocation, доступная вызываемой функции, содержит:
- в полях
caller
,originCaller
— адрес отправителя в формате Waves (26 байт), - в полях
callerPublicKey
,originCallerPublicKey
— открытый ключ пользователя MetaMask (64 байта).
В случае верификации скриптом ассета Ethereum-like транзакция интерпретируется как структура TransferTransaction или InvokeScriptTransaction, которая содержит:
- в поле
sender
— адрес отправителя в формате Waves (26 байт), - в поле
senderPublicKey
— открытый ключ пользователя MetaMask (64 байта). - в поле
bodyBytes
— пустой массив байтов, - в поле
version
— 0.
Подпись транзакции недоступна в скрипте ассета.
Ethereum-like транзакция никогда не проверяется смарт-аккаунтом или функцией-верификатором dApp-скрипта, поскольку такая транзакция не может быть отправлена со смарт-аккаунта или dApp.
В Стандартной библиотеке версии 6:
- Функция addressFromPublicKey принимает на вход как публичный ключ аккаунта Waves (32 байта), так и публичный ключ аккаунта MetaMask (64 байта) и возвращает адрес в формате Waves (26 байт).
- Функция transferTransactionById возвращает Ethereum-like транзакцию по ее идентификатору, если эта транзакция была интерпретирована как транзакция перевода. Массив
proofs
при этом содержит 8 пустых значений.
# Биржевой ордер
В транзакции обмена один из ордеров (или оба) может быть с подписью ECDSA. Подпись ECDSA поддерживается только для ордеров версии 4.
Библиотека Signer не поддерживает подписание ордера, и нужно вызывать функцию signOrder()
ProviderMetamask напрямую.
Приложение вызывает функцию
signOrder()
ProviderMetamask, передавая параметры ордера.• ID ассетов следует указывать в формате Waves: 32 байта в base58. Для WAVES следует указывать строку
WAVES
.•
senderPublicKey
должен отсутствовать.ProviderMetamask передает ордер в MetaMask как структуру данных, в соответствии с EIP-712.
MetaMask открывает окно, в котором пользователь может посмотреть детали ордера, подписать его или отклонить.
MetaMask возвращает подпись ECDSA для этой структуры данных.
Приложение передает подписанный ордер в матчер.
Матчер исполняет ордера и формирует транзакции обмена.
Пример подписания ордера см. в подразделе Примеры использования MetaMask ниже.
# Сообщение
Веб-приложение может запросить подпись произвольной строки от имени пользователя MetaMask, используя функцию signMessage('...')
в Signer. ProviderMetamask вызывает версию 4 функции signTypedData
API MetaMask и передает следующую структуру:
[
{
"types": {
"EIP712Domain": [
{
"name": "chainId",
"type" :"uint256"
},
],
"Message": [
{
"name": "text",
"type": "string"
}
]
},
"domain": {
"chainId": 87
},
"primaryType": "Message",
"message": {
"text": "some_custom_message"
}
}
]
В качестве chainId
указывается 87 для Mainnet, 84 для Testnet, 83 для Stagenet.
Чтобы проверить подпись, нужно восстановить адрес пользователя из подписи и подписанных данных с помощью версии 4 функции recoverTypedSignature
и сравнить с ожидаемым. См. пример в разделе signMessage документации Signer.
# Примеры использования MetaMask
# Вызов скрипта
Пример подключения к сети Waves и подписания транзакции вызова скрипта можно посмотреть в приложении Waves Dapp Ui.
Вставьте адрес dApp, например 3N62UHvyvvdresjwfsmW4UX2ffDjcDPAkbn на Testnet или 3MRuzZVauiiX2DGwNyP8Tv7idDGUy1VG5bJ на Stagenet.
Нажмите Sign In и выберите Sign in with Metamask. Подтвердите в MetaMask подключение к сети. Waves Dapp Ui по умолчанию отображает адрес пользователя в формате Waves, но с помощью кнопок и доступно переключение между форматами адресов.
Чтобы получить WAVES для уплаты комиссий за транзакции на Testnet или Stagenet, скопируйте адрес в формате Waves и воспользуйтесь Testnet Faucet или Stagenet Faucet.
Укажите аргументы вызываемой функции и (если требуется) платежи. Подтвердите транзакцию в MetaMask. Статус транзакции отображается в MetaMask на вкладке Активность с небольшой задержкой.
По ссылке на транзакцию из MetaMask открывается страница транзакции в Waves Explorer.
Пример кода приведен в документации ProviderMetamask. Для работы приложения необходимо установить библиотеку ProviderMetamask и последнюю версию Signer.
# Подписание ордера
Пример подписания ордера можно посмотреть на странице Signer test.
В настройках страницы выберите сеть Waves: Mainnet, Testnet или Stagenet. Затем нажмите Login via Metamask. В поле Order заполните параметры ордера и нажмите Sign. В MetaMask разрешите доступ к открытому ключу, затем подтвердите подписание данных. Подпись ордера появится на странице Dapp test в поле sign.
Пример кода приведен в документации ProviderMetamask.
# Подписание сообщения
Пример подписания сообщения также можно посмотреть на странице Signer test.
В настройках страницы выберите сеть Waves: Mainnet, Testnet или Stagenet. В поле Message вставьте сообщение и нажмите Sign. В MetaMask разрешите доступ к открытому ключу, затем подтвердите подписание данных. Подпись сообщения появится на странице Dapp test в поле sign.