# Signer
# Общие сведения
Signer — TypeScript/JavaScript-библиотека, которая позволяет вашему веб-приложению подписывать и отправлять транзакции от имени пользователей, не запрашивая у них секретную фразу (seed) или закрытый ключ.
Исходный код библиотеки доступен на Github: https://github.com/wavesplatform/signer.
# Провайдер
Для работы Signer необходимо подключить внешнюю библиотеку — Провайдер. Провайдер обеспечивает безопасное хранение приватных данных пользователя. Ни ваше приложение, ни Signer не имеют доступа к закрытому ключу и секретной фразе (seed) пользователя.
Провайдер выполняет аутентификацию пользователя и генерацию цифровой подписи.
Signer предоставляет приложению удобный протокол взаимодействия с Провайдером, а также отправляет транзакции в блокчейн.
В данный момент вы можете подключить один из следующих Провайдеров:
ProviderKeeper использует браузерное расширение Keeper Wallet.
ProviderKeeperMobile использует мобильное приложение Keeper Wallet.
ProviderCloud, разработанный командой WX Network, использует аккаунт WX Network на основе Email.
ProviderWeb, разработанный командой WX Network, использует аккаунт, созданный или импортированный в веб-приложение WX Network через секретную фразу или приватный ключ.
ProviderLedger использует устройство Ledger Nano X или Ledger Nano S.
ProviderMetaMask использует браузерное расширение MetaMask.
Пользователям MetaMask в сети Waves доступны только перевод токена и вызов скрипта. Подробнее см. в разделе Подписание транзакций и ордеров в MetaMask.
ProviderSeed создает аккаунт пользователя из секретной фразы. ProviderSeed можно использовать на этапе разработки и отладки приложения.
Вы также можете разработать собственный Провайдер, см. подраздел Интерфейс Провайдера.
# Signer + ProviderWeb: как это работает
Получив от Signer запрос на подписание транзакции, ProviderWeb открывает iframe, в котором пользователь может посмотреть детали транзакции, подтвердить или отклонить ее. Получив подтверждение от пользователя, ProviderWeb генерирует цифровую подпись. Процесс подписания транзакции продемонстрирован в следующем видео.
# Ограничения
Signer поддерживает все типы транзакций, кроме транзакций обмена и транзакций обновления информации ассета.
# Начало работы
# 1. Установка библиотек Signer и Провайдера
Чтобы установить Signer, используйте команду
npm i @waves/signer
Чтобы установить ProviderKeeper, используйте команду
npm i @waves/provider-keeper
Чтобы установить ProviderKeeperMobile, используйте команду
npm i @keeper-wallet/provider-keeper-mobile
Чтобы установить ProviderCloud от WX Network, используйте команду
npm i @waves.exchange/provider-cloud
Для Windows используйте следующий формат:
npm i '@waves.exchange/provider-cloud'
Чтобы установить ProviderWeb от WX Network, используйте команду
npm i @waves.exchange/provider-web
Для Windows используйте следующий формат:
npm i '@waves.exchange/provider-web'
Чтобы установить ProviderLedger, используйте команду
npm i @waves/provider-ledger
Чтобы установить ProviderMetamask, используйте команду
npm i @waves/provider-metamask
Чтобы установить ProviderSeed, используйте команду
npm i @waves/provider-seed @waves/waves-transactions
# 2. Подключение библиотек
Инициализируйте библиотеки в приложении.
Для работы с Testnet и ProviderKeeper:
import { Signer } from '@waves/signer'; import { ProviderKeeper } from '@waves/provider-keeper'; const signer = new Signer({ // Укажите адрес ноды, подключенной к Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com', }); const keeper = new ProviderKeeper(); signer.setProvider(keeper);
Для работы с Testnet и ProviderKeeperMobile:
import { Signer } from '@waves/signer'; import { ProviderKeeperMobile } from '@keeper-wallet/provider-keeper-mobile'; const signer = new Signer({ // Укажите адрес ноды, подключенной к Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com', }); const keeperMobile = new ProviderKeeperMobile(); signer.setProvider(keeperMobile);
Вы можете указать данные своего приложения для отображения в Keeper Wallet:
import { ProviderKeeperMobile } from '@keeper-wallet/provider-keeper-mobile'; const keeperMobile = new ProviderKeeperMobile({ // все параметры необязательные name: 'My dApp', // имя приложения icon: 'https://avatars.githubusercontent.com/u/96250405', // значок приложения });
**🛈** Рекомендуемый размер значка — не менее 180×180 px.
Для работы с Testnet и WX Network ProviderCloud:
import { Signer } from '@waves/signer'; import { ProviderCloud } from '@waves.exchange/provider-cloud'; const signer = new Signer({ // Укажите адрес ноды, подключенной к Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com' }); signer.setProvider(new ProviderCloud())
Для работы с Testnet и WX Network ProviderWeb:
import { Signer } from '@waves/signer'; import { ProviderWeb } from '@waves.exchange/provider-web'; const signer = new Signer({ // Укажите адрес ноды, подключенной к Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com' }); signer.setProvider(new ProviderWeb('https://testnet.wx.network/signer/'))
Для работы с Testnet и ProviderLedger:
import { Signer } from '@waves/signer'; import { ProviderLedger } from '@waves/provider-ledger'; const signer = new Signer({ // Specify URL of the node on Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com' }); signer.setProvider(new ProviderLedger({ // Specify chain ID of Testnet wavesLedgerConfig: { networkCode: 84, }, }));
Для работы с Testnet и ProviderMetamask:
import { Signer } from '@waves/signer'; import { ProviderMetamask } from '@waves/provider-metamask'; const signer = new Signer({ // Specify URL of the node on Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com' }); signer.setProvider(new ProviderMetamask()); }));
Для работы с Testnet и ProviderSeed:
import { Signer } from '@waves/signer'; import { ProviderSeed } from '@waves/provider-seed'; import { libs } from '@waves/waves-transactions'; const seed = libs.crypto.randomSeed(15); const signer = new Signer({ // Укажите адрес ноды, подключенной к Testnet NODE_URL: 'https://nodes-testnet.wavesnodes.com' }); signer.setProvider(new ProviderSeed(seed));
Для работы с Mainnet и ProviderKeeper:
import { Signer } from '@waves/signer'; import { ProviderKeeper } from '@waves/provider-keeper'; const signer = new Signer(); const keeper = new ProviderKeeper(); signer.setProvider(keeper);
Для работы с Mainnet и ProviderKeeperMobile:
import { Signer } from '@waves/signer'; import { ProviderKeeperMobile } from '@keeper-wallet/provider-keeper-mobile'; const signer = new Signer(); const keeperMobile = new ProviderKeeperMobile(); signer.setProvider(keeperMobile);
Вы можете указать данные своего приложения для отображения в Keeper Wallet:
import { ProviderKeeperMobile } from '@keeper-wallet/provider-keeper-mobile'; const keeperMobile = new ProviderKeeperMobile({ // все параметры необязательные name: 'My dApp', // имя приложения icon: 'https://avatars.githubusercontent.com/u/96250405', // значок приложения });
🛈 Рекомендуемый размер значка — не менее 180×180 px.
Для работы с Mainnet и WX Network ProviderCloud:
import { Signer } from '@waves/signer'; import { ProviderCloud } from '@waves.exchange/provider-cloud'; const signer = new Signer(); signer.setProvider(new ProviderCloud());
Для работы с Mainnet и WX Network ProviderWeb:
import { Signer } from '@waves/signer'; import { ProviderWeb } from '@waves.exchange/provider-web'; const signer = new Signer(); signer.setProvider(new ProviderWeb());
Для работы с Mainnet и ProviderLedger:
import { Signer } from '@waves/signer'; import { ProviderLedger } from '@waves/provider-ledger'; const signer = new Signer(); const provider = new ProviderLedger(); signer.setProvider(provider);
Для работы с Mainnet и ProviderMetamask:
import { Signer } from '@waves/signer'; import { ProviderMetamask } from '@waves/provider-metamask'; const signer = new Signer(); const provider = new ProviderMetamask(); signer.setProvider(provider);
Теперь ваше приложение может использовать функции Signer.
# 3. Базовый пример
Ваше приложение готово к работе с блокчейном Waves. Попробуем использовать базовые функции: аутентифицировать пользователя, получить его баланс, перевести токены.
const user = await signer.login();
const balances = await signer.getBalance();
const [broadcastedTransfer] = await signer
.transfer({amount: 100000000, recipient: 'alias:T:merry'}) // Перевод 1 WAVES алиасу merry
.broadcast(); // Promise будет разрешен после подписания транзакции пользователем и получения ответа ноды
const [signedTransfer] = await signer
.transfer({amount: 100000000, recipient: 'alias:T:merry'}) // Перевод 1 WAVES алиасу merry
.sign(); // Promise будет разрешен после подписания транзакции пользователем
# Другие примеры
- Приложение, реализующее кнопку сбора пожертвований: https://github.com/vlzhr/crypto-donate.
- Приложение, реализующее отправку транзакций трех типов: https://github.com/vlzhr/waves-signer-example.
# Конструктор
new Signer({
NODE_URL: 'string',
})
Создает объект с перечисленными ниже методами.
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
NODE_URL | https://nodes.wavesnodes.com | Нода, используемая для доступа к блокчейну |
# Методы
В коде можно использовать типы TypeScript.
# Данные пользователя
# login
Выполняет вход в аккаунт пользователя; если у пользователя еще нет аккаунта — создает его.
login();
Возвращает: Promise пользовательских данных: адреса и открытого ключа.
При использовании ProviderMetamask возвращается пустой открытый ключ.
Пример вызова:
const {address, publicKey} = await signer.login();
Пример результата:
{
address: '3P8pGyzZL9AUuFs9YRYPDV3vm73T48ptZxs',
publicKey: 'FuChbN7t3gvW5esgARFytKNVuHSCZpXSYf1y3eDSruEN',
}
# logout
Выполняет выход из аккаунта.
logout();
Возвращает: Promise<void>.
Пример вызова:
await signer.logout();
# getBalance
Если пользователь вошел в аккаунт, функция получает текущий баланс всех ассетов в портфеле пользователя.
getBalance();
Возвращает: Promise списка ассетов и их балансов.
Пример вызова:
const balances = await signer.getBalance();
Пример результата:
[{
assetId: 'WAVES',
assetName: 'Waves',
decimals: 8,
amount: 100000000,
isMyAsset: false,
tokens: 1,
sponsorship: null,
isSmart: false
},
{
assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
assetName: 'CoffeeCoin',
decimals: 3,
amount: 1500,
isMyAsset: false,
tokens: 1.5,
isSmart: false,
sponsorship: 500
}]
Поля результата:
Имя поля | Описание |
---|---|
assetId | Идентификатор ассета в кодировке Base58 |
assetName | Название ассета |
decimals | Количество знаков после запятой в балансе ассета |
amount | Баланс ассета, умноженный на 10decimals . Например, для WAVES decimals равно 8, поэтому фактическое количество WAVES умножается на 108. { "WAVES": 677728840 } означает 6,77728840 WAVES |
isMyAsset | true , если ассет выпущен текущим пользователем |
tokens | Баланс ассета для отображения в приложении |
sponsorship | Количество спонсорского ассета, взимаемое с пользователей (эквивалент 0,001 WAVES), умноженное на 10decimals null — если токен не является спосорским |
isSmart | true для смарт-ассетов |
# getSponsoredBalances
Если пользователь вошел в аккаунт, функция получает текущий баланс спонсорских ассетов в портфеле пользователя. См. раздел Спонсирование.
getSponsoredBalances();
Возвращает: Promise списка ассетов и их балансов.
Пример вызова:
const sponsoredBalances = await signer.getSponsoredBalances();
Пример результата:
[{
assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
assetName: 'CoffeeCoin',
decimals: 3,
amount: 1500,
isMyAsset: false,
tokens: 1.5,
isSmart: false,
sponsorship: 500
}]
Поля результата такие же, как у метода getBalance.
# Создание транзакций
Следующие методы создают транзакции (но не подписывают их и не отправляют в блокчейн):
- alias
- burn
- cancelLease
- data
- invoke
- issue
- lease
- massTransfer
- reissue
- setAssetScript
- setScript
- sponsorship
- transfer
Проверьте, какие типы транзакций поддерживает используемый вами Провайдер.
# Общие параметры
Каждый из методов создания транзакции имеет необязательные параметры, которые в большинстве случаев не требуется указывать в явном виде:
Имя поля | Описание | Значение по умолчанию |
---|---|---|
chainId | 'W'.charCodeAt(0) или 87 — Mainnet 'T'.charCodeAt(0) или 84 — Testnet 'S'.charCodeAt(0) или 83 — Stagenet | Определяется конфигурацией ноды Waves, указанной в Конструкторе |
fee | Комиссия за транзакцию | Минимальная комиссия за транзакцию, см. раздел Комиссия за транзакцию. ⚠️ Внимание! При расчете значения по умолчанию для транзакции вызова скрипта не учитываются действия скрипта. Подробнее в разделе invoke ниже |
proofs | Массив подтверждений транзакции | Добавляется методом sign или broadcast (см. подраздел Как подписать и отправить транзакцию). Если вы указываете подтверждение вручную, оно также добваляется в массив |
senderPublicKey | Открытый ключ отправителя транзакции в кодировке Base58 | Возвращается методом login |
# Как подписать и отправить транзакцию
Каждый из методов создания транзакции возвращает объект, у которого есть методы sign
и broadcast
.
Чтобы подписать транзакцию, используйте метод sign
. Пример:
signer.invoke({
dApp: address,
call: { function: name, args: convertedArgs },
}).sign();
Чтобы подписать транзакцию и сразу отправить ее в блокчейн, используйте метод broadcast
. Пример:
signer.invoke({
dApp: address,
call: { function: name, args: convertedArgs },
}).broadcast();
В методе
broadcast
можно использовать те же опции, что и в методе signer.broadcast, описание которого приведено ниже.
Вы можете подписать или отправить сразу несколько транзакций. Пример:
signer.alias({ 'new_alias', })
.data([{ key: 'value', type: 'integer', value: 1 ])
.transfer({ recipient: '3P8pGyzZL9AUuFs9YRYPDV3vm73T48ptZxs', amount: 10000 })
}).broadcast();
# alias
Создает транзакцию создания псевдонима.
alias(data: {
alias: 'string'
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
alias* | Короткое, удобное для запоминания имя адреса. См. Псевдоним |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
alias: 'new_alias',
}
const [tx] = await signer
.alias(data)
.broadcast();
# burn
Создает транзакцию сжигания токена.
burn(data: {
assetId*: 'string',
quantity*: LONG,
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
assetId* | Идентификатор сжигаемого ассета в кодировке Base58 | |
quantity* | Количество сжигаемого ассета, умноженное на 10decimals. Например, для WAVES decimals равно 8, поэтому фактическое количество WAVES умножается на 108. { "WAVES": 677728840 } означает 6,77728840 WAVES |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
assetId: '4uK8i4ThRGbehENwa6MxyLtxAjAo1Rj9fduborGExarC',
quantity: 100,
}
const [tx] = await signer
.burn(data)
.broadcast();
# cancelLease
Создает транзакцию закрытия лизинга.
cancelLease(data: {
leaseId: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
leasetId* | Идентификатор транзакции лизинга в кодировка Base58 |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
leaseId: '69HK14PEHq2UGRfRYghVW8Kc3487uJaoUmk2ntT4kw7X',
}
const [tx] = await signer
.cancelLease(data)
.broadcast();
# data
Создает транзакцию данных.
data(data: [{
key: 'string',
type: 'string' | 'integer' | 'binary' | 'boolean',
value: 'string' | number | boolean,
])
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
key* | Ключ записи. Не более 100 символов | |
type | Тип записи | |
value* | Значение записи. Не более 5 Кбайт |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const records = [
{ key: 'name', type: 'string', value: 'Lorem ipsum dolor sit amet' },
{ key: 'value', type: 'integer', value: 1234567 },
{ key: 'flag', type: 'boolean', value: true }
]
const [tx] = await signer
.data({ data: records })
.broadcast();
# invoke
Создает транзакцию вызова скрипта.
invoke(data: {
dApp: 'string',
fee: LONG,
payment: [{
assetId: 'string',
amount: LONG,
}],
call: {
function: 'string',
args: [{
type: 'integer' | 'string' | 'binary' | 'boolean' | 'list',
value: number | 'string' | 'string(base64)' | boolean | array,
}],
},
feeAssetId: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
dApp* | Адрес в кодировке Base58 или псевдоним (с префиксом alias:T: ) dApp-скрипта, который нужно вызвать | |
fee | ⚠️ Внимание! Значение по умолчанию не учитывает действия скрипта. В случае вызова функции dApp-скрипта, которая выполняет выпуск токенов, не являющихся NFT, рассчитайте комиссию самостоятельно, в соответствии с описанием в разделе Транзакция вызова скрипта | |
payment | Платежи, приложенные к вызову. Не более 10 платежей | |
payment.assetId* | Идентификатор ассета платежа в кодировке Base58. WAVES или null соответствуют WAVES | |
payment.amount* | Количество ассета, умноженное на 10decimals . Например, для WAVES decimals равно 8, поэтому фактическое количество WAVES умножается на 108. { "WAVES": 677728840 } означает 6,77728840 WAVES | |
call | Вызывается функция по умолчанию | Параметры вызываемой функции |
call.function* | Имя вызываемой функции | |
call.args* | Аргументы вызываемой функции | |
call.args.type* | Тип аргумента | |
call.args.value* | Значение аргумента | |
feeAssetId | WAVES | Идентификатор спонсорского ассета, в котором будет уплачена комиссия за транзакцию, в кодировке Base58. См. раздел Спонсирование. null или отсутствующий параметр означает WAVES |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
dApp: '3Fb641A9hWy63K18KsBJwns64McmdEATgJd',
fee: 1000000,
payment: [{
assetId: '73pu8pHFNpj9tmWuYjqnZ962tXzJvLGX86dxjZxGYhoK',
amount: 7,
}],
call: {
function: 'foo',
args: [
{ type: 'integer', value: 1 },
{ type: 'binary', value: 'base64:AAA=' },
{ type: 'string', value: 'foo' },
{ type: 'boolean', value: true },
{ type: 'list', value: [
{ type: 'string', value: 'alpha' },
{ type: 'string', value: 'beta' },
{ type: 'string', value: 'gamma' }
]
}
],
},
}
const [tx] = await signer
.invoke(data)
.broadcast();
# issue
Создает транзакцию выпуска.
issue(data: {
name: 'string',
decimals: number,
quantity: LONG,
reissuable: boolean,
description: 'string',
script: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
name* | Название ассета | |
decimals* | Количество знаков после запятой | |
quantity* | Количество ассета, умноженное на 10decimals | |
reissuable* | true – довыпуск возможен;false — довыпуск невозможен | |
description* | Описание ассета | |
script | Скрипт ассета в кодировке Base64 (с префиксом base64: ) |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
name: 'MyToken',
decimals: 8,
quantity: 100000000000,
reissuable: true,
description: 'It is a gaming token',
}
const [tx] = await signer
.issue(data)
.broadcast();
# lease
Создает транзакцию лизинга.
lease(data: {
amount: LONG,
recipient: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
amount* | Количество WAVES, умноженное на 10decimals . { "WAVES": 677728840 } означает 6,77728840 WAVES | |
recipient* | Адрес получателя в кодировке Base58 или алиас получателя (с префиксом alias:T: ) |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
amount: 10000,
recipient: 'alias:T:merry',
}
const [tx] = await signer
.lease(data)
.broadcast();
# massTransfer
Создает транзакцию массового перевода.
massTransfer(data: {
assetId: 'string',
transfers: [{
amount: LONG,
recipient: 'string',
}],
attachment: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
assetId | WAVES | Идентификатор ассета в кодировке Base58 |
transfers* | Список переводов | |
transfers.amount* | Количество ассета, умноженное на 10decimals . Например, для WAVES decimals равно 8, поэтому фактическое количество WAVES умножается на 108. { "WAVES": 677728840 } означает 6,77728840 WAVES | |
transfers.recipient* | Адрес получателя в фодировке Base58 или алиас получателя (с префиксом alias:T: ) | |
attachment | Произвольные данные: байты в кодировке Base58. Обычно используются для комментария к переводу. Не более 140 байт |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const crypto = require('@waves/ts-lib-crypto')
const data = {
transfers: [
{
amount: 100,
recipient: '3P23fi1qfVw6RVDn4CH2a5nNouEtWNQ4THs',
},
{
amount: 200,
recipient: 'alias:T:merry',
}],
attachment: crypto.base58Encode(crypto.stringToBytes('sample message for recipient'))
]
const [tx] = await signer
.massTransfer(data)
.broadcast();
# reissue
Создает транзакцию довыпуска.
reissue(data: {
assetId: 'string',
quantity: LONG,
reissuable: boolean,
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
assetId* | Идентификатор ассета в кодировке Base58 | |
quantity* | Количество ассета к довыпуску, умноженное на 10decimals | |
reissuable* | true – повторный довыпуск возможен.false — повторный довыпуск невозможен |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx'
quantity: 100000000000,
reissuable: true,
}
const [tx] = await signer
.reissue(data)
.broadcast();
# setAssetScript
Создает транзакцию установки скрипта ассета.
setAssetScript(data: {
assetId: 'string',
script: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
assetId* | Идентификатор ассета в кодировке Base58 | |
script | Скрипт ассета в кодировке Base64 (с префиксом base64: ) |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
script: 'base64:AwZd0cYf...',
}
const [tx] = await signer
.setAssetScript(data)
.broadcast();
# setScript
Создает транзакцию установки скрипта.
setScript(data: {
script: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
script | Скрипт аккаунта или dApp-скрипт в кодировке Base64 (с префиксом base64: ). null — отмена установки скрипта |
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
script: 'base64:AAIDAAAAAAAAAAQIARIAAAAAAAAAAA...',
}
const [tx] = await signer
.setScript(data)
.broadcast();
# sponsorship
Создает транзакцию спонсирования.
sponsorship(data: {
assetId: 'string',
minSponsoredAssetFee: LONG,
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
assetId* | Идентификатор ассета в кодировке Base58 | |
minSponsoredAssetFee | Количество спонсорского ассета, взимаемое с пользователей (эквивалент 0,001 WAVES), умноженное на 10decimals |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const data = {
assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
minSponsoredAssetFee: 314,
}
const [tx] = await signer
.sponsorship(data)
.broadcast();
# transfer
Создает транзакцию перевода.
transfer(data: {
recipient: 'string',
amount: LONG,
assetId: 'string',
attachment: 'string',
feeAssetId: 'string',
})
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
recipient* | Адрес получателя в кодировке Base58 или алиас получателя (с префиксом alias:T: ) | |
amount* | Количество ассета, умноженное на 10decimals . Например, для WAVES decimals равно 8, поэтому фактическое количество WAVES умножается на 108. { "WAVES": 677728840 } означает 6,77728840 WAVES | |
assetId | WAVES | Идентификатор ассета в кодировке Base58. null или отсутствующий параметр означает WAVES |
attachment | Произвольные данные: байты в кодировке Base58. Обычно используются для комментария к переводу. Не более 140 байт | |
feeAssetId | WAVES | Идентификатор спонсорского ассета, в котором будет уплачена комиссия за транзакцию, в кодировке Base58. См. раздел Спонсирование. null или отсутствующий параметр означает WAVES |
* Обязательный параметр.
См. Общие параметры для описания остальных параметров.
Пример вызова:
const crypto = require('@waves/ts-lib-crypto')
const data = {
recipient: '3P8pGyzZL9AUuFs9YRYPDV3vm73T48ptZxs',
amount: 10000,
attachment: crypto.base58Encode(crypto.stringToBytes('sample message for recipient'))
}
const [tx] = await signer
.transfer(data)
.broadcast();
# batch
Создает список транзакций.
batch([{
type: number,
... // поля, зависящие от типа транзакции
}])
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
type* | Идентификатор типа транзакции |
* Обязательный параметр.
Пример вызова:
const [transfer, alias, issue] = await signer.batch([
{
type: 4,
recipient: 'alias:T:merry',
amount: 100000000
},
{
type: 10,
alias: 'send33'
},
{
type: 3,
name: 'SomeTokenName',
description: 'Some Token Description',
reissuable: false,
quantity: 100,
decimals: 1
}
]).sign(); // Или broadcast
В этом примере метод sign
возвращает массив подписанных транзакций, в том же порядке, в котором они были приведены в batch
.
# Прочие методы
# broadcast
Оправляет ранее подписанные транзакции в блокчейн.
broadcast(tx,[options])
Возвращает: Promise ответа ноды. См. описание метода POST /transactions/broadcast Node API.
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
tx* | Подписанная транзакция или массив подписанных транзакций | |
options.chain | false | [Тип: boolean] Отправлять следующую транзакцию только после того, как в блокчейн добавлен блок с предыдущей транзакцией и затем еще количество блоков, указанное в параметре options.confirmations |
options.confirmations | -1 | Уровень подтверждения, при котором будет разрешен Promise: меньше 0 – Promise разрешается, когда транзакция попадает в UTX pool 0 – Promise разрешается, когда блок, содержащий транзакцию, попадает в блокчейн 1 – Promise разрешается, когда в блокчейн добавляется еще один блок и т. д. |
* Обязательный параметр.
Пример вызова:
const [transfer1] = await signer.transfer({amount: 1, recipient: 'alias:T:merry'}).sign();
const [transfer2] = await signer.transfer({amount: 1, recipient: 'alias:T:merry'}).sign();
await signer.broadcast([transfer1, transfer2], {chain: true, confirmations: 2});
В этом примере последовательность событий следующая:
- Транзакция
transfer1
передается на ноду и помещается в UTX pool. - Блок с транзакцией
transfer1
и еще два блока добавляются в блокчейн. - Транзакция
transfer2
передается на ноду и помещается в UTX pool. - Блок с транзакцией
transfer2
и еще два блока добавляются в блокчейн. - Происходит разрешение Promise, и вы можете сообщить пользователю, что его транзакции подтверждены.
# getNetworkByte
Получает байт сети.
getNetworkByte();
Возвращает: Promise байта сети.
Пример вызова:
const chainId = signer.getNetworkByte();
# setProvider
Устанавливает Провайдера, который используется для подписания транзакций. Требования к Провайдеру приведены в разделе Интерфейс Провайдера.
setProvider(provider);
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
provider* | Объект, который реализует интерфейс провайдера |
* Обязательный параметр.
Пример вызова:
signer.setProvider(new Provider());
# signMessage
Получает цифровую подпись пользователя для заданного сообщения. Проверка подписи позволяет убедиться, что аккаунт Waves принадлежит именно этому пользователю.
signMessage(data: string | number)
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
data* | Подписываемые данные: строка или число. Если указано число, оно вначале преобразуется в строку |
* Обязательный параметр.
Пример вызова:
const signature = await signer.signMessage('Ride the Waves!')
Проверка подписи
Все провайдеры, кроме ProviderMetamask
Провайдеры добавляют префикс [255, 255, 255, 1] к подписываемым байтам. Это сделано для того, чтобы в этом методе было невозможно подписать данные транзакций, что может привести к фишингу.
Пример проверки подписи:
const crypto = require('@waves/ts-lib-crypto');
const userData = await signer.login();
const signature = await signer.signMessage('Ride the Waves!')
crypto.verifySignature(userData.publicKey, [255, 255, 255, 1, ...crypto.stringToBytes('Ride the Waves!')], signature))
ProviderMetamask
ProviderMetamask использует спецификацию EIP-712 и версию 4 функции signTypedData
API MetaMask. На подпись передается следующая структура:
[
{
"types": {
"EIP712Domain": [
{
"name": "chainId",
"type" :"uint256"
},
],
"Message": [
{
"name": "text",
"type": "string"
}
]
},
"domain": {
"chainId": <87|84|83>
},
"primaryType": "Message",
"message": {
"text": "<some custom message>"
}
}
]
Чтобы проверить подпись, нужно восстановить адрес пользователя из подписи и подписанных данных с помощью версии 4 функции recoverTypedSignature
и сравнить с ожидаемым.
Пример проверки подписи:
const { recoverTypedSignature } = require('@metamask/eth-sig-util');
const { wavesAddress2eth } = require('@waves/node-api-js');
const userData = await signer.login();
const signature = await signer.signMessage('Ride the Waves!')
const msg = {
"types": {
"EIP712Domain": [
{
"name": "chainId",
"type" :"uint256"
},
],
"Message": [
{
"name": "text",
"type": "string"
}
]
},
"domain": {
"chainId": 'T'.charCodeAt(0) // 'W'.charCodeAt(0) for Mainnet
},
"primaryType": "Message",
"message": {
"text": "Ride the Waves!"
}
};
const recovered = recoverTypedSignature({
data: msg,
signature: signature,
version: 'V4'
});
recovered === wavesAddress2eth(userData.address)
# waitTxConfirm
Ожидает появления транзакции в блокчейне.
waitTxConfirm(tx, confirmations)
Параметры:
Имя параметра | Значение по умолчанию | Описание |
---|---|---|
tx* | Транзакция или массив транзакций, отправленных в блокчейн | |
confirmations* | Количество блоков, добавленных в блокчейн после блока, содержащего транзакцию |
* Обязательный параметр.
Пример вызова:
const [tx] = await signer
.transfer({amount: 10000000, recipient: 'alias:T:merry'})
.broadcast();
signer.waitTxConfirm(tx, 1).then((tx) => {
// Требуется еще один блок в блокчейне
}});
# Интерфейс Провайдера
⚠️ Чтобы обеспечить конфиденциальность данных пользователя, Провайдер следует реализовывать на основе
iframe
.
Провайдер должен предоставлять следующий интерфейс:
interface Provider {
/**
* Signer подписывается на события login в Провайдере
* При срабатывании Провайдер должен передать данные пользователя: адрес и публичный ключ
* Для последующей отписки Signer вызывает функцию off
*/
on(
event: 'login',
handler:({ address: string; publicKey: string }) => any
) => Provider;
/**
* Signer подписывается на события logout в Провайдере
* Для последующей отписки Signer вызывает функцию off
*/
on( event: 'logout', handler:() => any) => Provider;
/**
* Signer подписывается на первое событие login в Провайдере
* При срабатывании Провайдер должен передать данные пользователя:
* адрес и публичный ключ, а также выполнить отписку
* Отписка не нужна
*/
once(
event: 'login',
handler:({ address: string; publicKey: string }) => any
) => Provider;
/**
* Signer подписывается на первое событие logout в Провайдере
* При срабатывании Провайдер должен выполнить отписку
*/
once( event: 'logout', handler:() => any) => Provider;
/**
* Signer отписывается от событий в Провайдере, на которые были подписки
*/
off(
event: 'login',
handler:({ address: string; publicKey: string }) => any
) => Provider;
off( event: 'logout', handler:() => any) => Provider;
/**
* Устанавливает соединение с нодой Waves
* @param options
*/
connect(options: {NODE_URL: string, NETWORK_BYTE: number}): Promise<void>;
/**
* Выполняет вход в аккаунт пользователя
*/
login(): Promise<{address: string, publicKey: string}>;
/**
* Выполняет выход из аккаунта пользователя
*/
logout(): Promise<void>;
/**
* Подписывает произвольную строку
* @param data
*/
signMessage(data: string | number): Promise<string>;
/**
* Подписывает типизированные данные
* @param data
*/
signTypedData(data: Array<TypedData>): Promise<string>;
/**
* Подписывает транзакции в массиве
* Здесь SignedTx<T> — любая транзакция, T[] — массив любых транзакций
* @param list
*/
sign<T extends SignerTx>(toSign: T[]): Promise<SignedTx<T>>;
sign<T extends Array<SignerTx>>(toSign: T): Promise<SignedTx<T>>;
}
# Коды ошибок
Класс ошибки | Код | Тип | Описание |
---|---|---|---|
SignerOptionsError | 1000 | validation | Invalid signer options: NODE_URL, debug |
SignerNetworkByteError | 1001 | network | Could not fetch network from {NODE_URL}: Failed to fetch |
SignerAuthError | 1002 | authorization | Can't use method: getBalance. User must be logged in |
SignerProviderConnectError | 1003 | network | Could not connect the Provider |
SignerEnsureProviderError | 1004 | provider | Can't use method: login. Provider instance is missing 🛈 Возможные причины: пользователь в режиме Инкогнито или отключил cookie |
SignerProviderInterfaceError | 1005 | validation | Invalid provider properties: connect |
SignerProviderInternalError | 1006 | provider | Provider internal error: {...}. This is not error of signer. |
SignerApiArgumentsError | 1007 | validation | Validation error for invoke transaction: {...}. Invalid arguments: senderPublicKey |
SignerNetworkError | 1008 | network | Network Error |