/signer

TypeScript/JavaScript library for your web app for interacting with the Waves blockchain. Using Signer you can easily create and sign transactions.

Primary LanguageTypeScriptMIT LicenseMIT

Signer

Overview

Waves Signer is a TypeScript/JavaScript library for your web app for interacting with the Waves blockchain. Using Signer you can easily create and sign transactions.

Signer is a protocol for interacting with external Provider library that authenticates users with their accounts and signes transactions. Your web app and Signer itself do not have access to user's private key and SEED phrase.

For now, you can use one of the following Providers:

  • ProviderSeed developed by Waves team creates user account from SEED. ProviderSeed can be used at the app debugging stage.
  • ProviderWeb developed by Waves.Exchange is the wallet software that encryptes and stores user's private key and SEED phrase, making sure that users' funds are protected from hackers and malicious websites.

You can also develop your own Provider, see Provider Interface.

In code you can use TypeScript types.

Getting Started

1. Signer and Provider library installation

  • To install Signer library use

    npm i @waves/signer
  • To install ProviderSeed developed by Waves team, use

    npm i @waves/provider-seed @waves/waves-transactions
  • To install ProviderWeb developed by Waves.Exchange, use

    npm i @waves.exchange/provider-web

2. Library initialization

Add library initialization to your app.

  • For 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({
      // Specify URL of the node on Testnet
      NODE_URL: 'https://nodes-testnet.wavesnodes.com'
    });
    signer.setProvider(new ProviderSeed(seed));
  • For Testnet & Waves.Exchange ProviderWeb:

    import Signer from '@waves/signer';
    import Provider from '@waves.exchange/provider-web';
    
    const signer = new Signer({
      // Specify URL of the node on Testnet
      NODE_URL: 'https://nodes-testnet.wavesnodes.com'
    });
    signer.setProvider(new Provider());
  • For Mainnet & Waves.Exchange ProviderWeb:

    import Signer from '@waves/signer';
    import Provider from '@waves.exchange/provider-web';
    
    const signer = new Signer();
    signer.setProvider(new Provider());

After that you will be able to use Signer features in the app.

3. Basic example

Now your application is ready to work with Waves Platform. Let's test it by implementing basic functionality. For example, we could try to authenticate user, get his/her balances and transfer funds.

const user = await signer.login();
const balances = await signer.getBalance();
const [broadcastedTransfer] = await signer
  .transfer({amount: 100000000, recipient: 'alias:T:merry'}) // Transfer 1 WAVES to alias merry
  .broadcast(); // Promise will resolved after user sign and node response

const [signedTransfer] = await signer
  .transfer({amount: 100000000, recipient: 'alias:T:merry'}) // Transfer 1 WAVES to alias merry
  .sign(); // Promise will resolved after user sign

More examples

See example of an app that implements the donate button: https://github.com/vlzhr/crypto-donate.

Constructor

new Signer({
  NODE_URL: 'string',
})

Creates an object that features the following methods.

Parameters:

Parameter Default value Description
NODE_URL https://nodes.wavesnodes.com Node that is used to access a blockchain

Methods

User Info

login

Authenticates user with his/her account; creates account if it don't exist.

login();

Returns: Promise of user data: address and public key.

Usage:

const {address, publicKey} = await signer.login();

Output example:

{
  address: '3P8pGyzZL9AUuFs9YRYPDV3vm73T48ptZxs',
  publicKey: 'FuChbN7t3gvW5esgARFytKNVuHSCZpXSYf1y3eDSruEN',
}

logout

Logs user out.

logout();

Returns: Promise<void>.

Usage:

await signer.logout();

getBalance

If user logged in, provides balances of assets in user's portfolio.

getBalance();

Returns: Promise of list of balances.

Usage:

const balances = await signer.getBalance();

Output example:

[{
  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
}]

Output fields:

Field name Description
assetId Base58-encoded ID of the asset
assetName Name of the asset
decimals Number of decimal places in the asset amount
amount Amount of asset multiplied by 10^decimals. For example, decimals of WAVES is 8, so the real amount is multipied by 10^8. { "WAVES": 677728840 } means 6.77728840
isMyAsset true if current user is an asset issuer
tokens Amount of asset to display in app interface
sponsorship Amount of sponsored asset to be charged to users (per 0.001 WAVES) multiplied by 10^decimals
null if the asset is not sponsored
isSmart true for smart assets

getSponsoredBalances

If user logged in, provides balances of sponsored assets in user's portfolio.

getSponsoredBalances();

Returns: Promise of list of balances.

Usage:

const sponsoredBalances = await signer.getSponsoredBalances();

Output example:

[{
  assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
  assetName: 'CoffeeCoin',
  decimals: 3,
  amount: 1500,
  isMyAsset: false,
  tokens: 1.5,
  isSmart: false,
  sponsorship: 500
}]

Output fields are the same as in getBalance method.

Create transactions

The following methods create transactions (but do not sign or broadcast them):

Check which of these transactions are supported by your Provider.

Common fields

Each create transaction method has optional fields that you don't specify manually in most cases:

Field name Description Default value
chainId 'W'.charCodeAt(0) or 87 means Mainnet
'T'.charCodeAt(0) or 84 means Testnet
Defined by configuration of Waves node that is set in Constructor
fee Transaction fee Calculated automatically as described in Transaction fee section
proofs Array of transaction signatures Added by sign or broadcast method (see How to Sign and Broadcast Transactions). If you specify a proof manually, it is also added to the array
senderPublicKey Base58-encoded public key of transaction sender Returned by login method

How to Sign and Broadcast Transactions

Each create transaction method returns object that features the sign and broadcast methods.

To sign transaction use sign method. For example:

signer.invoke({
   dApp: address,
   call: { function: name, args: convertedArgs },
}).sign();

To sign transaction and immediately send it to blockchain use broadcast method. For example:

signer.invoke({
   dApp: address,
   call: { function: name, args: convertedArgs },
}).broadcast();

Note: this broadcast method has the same options as the signer.broadcast method that is described below.

You can sign or broadcast several transactions at once. For example:

signer.alias({ 'new_alias', })
  .data([{ key: 'value', type: 'number', value: 1 ])
  .transfer({ recipient: '3P8pGyzZL9AUuFs9YRYPDV3vm73T48ptZxs', amount: 10000 })
}).broadcast();

alias

Creates alias transaction.

alias(data: {
  alias: 'string'
})

Parameters:

Field name Default value Description
alias* Short and easy to remember name of address. See Alias for more information

See Common fields for other fields description.

Usage:

const data = {
  alias: 'new_alias',
}

const [tx] = await signer
  .alias(data)
  .broadcast();

burn

Creates burn transaction.

burn(data: {
    assetId*: 'string',
    quantity*: LONG,
})

Parameters:

Field name Default value Description
assetId* Base58-encoded ID of the asset to burn
quantity* Amount of asset multiplied by 10^decimals. For example, decimals of WAVES is 8, so the real amount is multipied by 10^8. { "WAVES": 677728840 } means 6.77728840

* Required field.

See Common fields for other fields description.

Usage:

const data = {
  assetId: '4uK8i4ThRGbehENwa6MxyLtxAjAo1Rj9fduborGExarC',
  quantity: 100,
}

const [tx] = await signer
  .burn(data)
  .broadcast();

cancelLease

Creates lease cancel transaction.

cancelLease(data: {
    leaseId: 'string',
})

Parameters:

Field name Default value Description
leasetId* Base58-encoded ID of the lease transaction

* Required field.

See Common fields for other fields description.

Usage:

const data = {
  leaseId: '69HK14PEHq2UGRfRYghVW8Kc3487uJaoUmk2ntT4kw7X',
}

const [tx] = await signer
  .cancelLease(data)
  .broadcast();

data

Creates data transaction.

data(data: [{
  key: 'string',
  type: 'string' | 'integer' | 'binary' | 'boolean',
  value: 'string' | number | boolean,
])

Parameters:

Field name Default value Description
key* Key of a record. Maximum of 100 characters
type Type of a record
value* Value of a record. Maximum of 5 Kbytes

* Required field.

See Common fields for other fields description.

Usage:

const data = [
  { key: 'name', type: 'string', value: 'Lorem ipsum dolor sit amet' },
  { key: 'value', type: 'number', value: 1234567 },
  { key: 'flag', type: 'boolean', value: true }
]

const [tx] = await signer
  .data(data)
  .broadcast();

invoke

Creates invoke scipt transaction.

invoke(data: {
  dApp: 'string',
  fee: LONG,
  payment: [{
    assetId: 'string',
    amount: LONG,
  }],
  call: {
    function: 'string',
    args: [{
      type: 'integer' | 'string' | 'binary',
      value: number | 'string',
    }],
  },
})

Parameters:

Field name Default value Description
dApp* Base58-encoded address or alias (with alias:T: prefix) of the dApp whose script should be invoked
fee We recommend to specify fee depending on number of action performed by called function (see Transaction Fee)
payment Payments attached to the transaction. Maximum of two payments
payment.assetId* Base58-encoded ID of the asset to pay. WAVES or null means WAVES
payment.amount* Amount of asset multiplied by 10^decimals. For example, decimals of WAVES is 8, so the real amount is multipied by 10^8. { "WAVES": 677728840 } means 6.77728840
call Default function should be invoked in the dApp Parameters for called function
call.function* Name of the function that is called
call.args* Arguments for the function that is called
call.args.type* Type of argument
call.args.value* Value of argument

* Required field

See Common fields for other fields description.

Usage:

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' }
    ],
  },
}

const [tx] = await signer
  .invoke(data)
  .broadcast();

issue

Creates issue transaction.

issue(data: {
  name: 'string',
  decimals: 'number',
  quantity: LONG,
  reissuable: boolean,
  description: 'string',
  script: 'string',
})

Parameters:

Field name Default value Description
name* Asset name
decimals* Number of digits in decimal part
quantity* Amount of asset multiplied by 10^decimals
reissuable* true – asset reissue is possible.
false — asset reissue is not possible
description* Asset description
script Base64-encoded script (with base64: prefix) to be attached to to asset

* Required field

See Common fields for other fields description.

Usage:

const data = {
  name: 'MyToken',
  decimals: 8,
  quantity: 100000000000,
  reissuable: true,
  description: 'It is a gaming token',
}

const [tx] = await signer
  .issue(data)
  .broadcast();

lease

Creates lease transaction.

lease(data: {
    amount: LONG,
    recipient: 'string',
})

Parameters:

Field name Default value Description
amount* Amount of WAVES multiplied by 10^8. For example, { "WAVES": 677728840 } means 6.77728840
recipient* Base58-encoded address or alias (with alias:T: prefix) of the recipient

* Required field

See Common fields for other fields description.

Usage:

const data = {
    amount: 10000,
    recipient: 'alias:T:merry',
}

const [tx] = await signer
  .lease(data)
  .broadcast();

massTransfer

Creates mass transfer transaction.

massTransfer(data: {
  assetId: 'string',
  transfers: [{
    amount: LONG,
    recipient: 'string',
  }],
  attachment: 'string',
})

Parameters:

Field name Default value Description
assetId WAVES Base58-encoded ID of the asset to transfer
transfers* List of transfers
transfers.amount* Amount of asset multiplied by 10^decimals. For example, decimals of WAVES is 8, so the real amount is multipied by 10^8. { "WAVES": 677728840 } means 6.77728840Amount of multiplied by 10^8.
transfers.recipient* Base58-encoded address or alias (with alias:T: prefix) of the recipient
attachment Optional data attached to the transaction. This field is often used to attach a comment to the transaction. The maximum data size is 140 bytes

* Required field

See Common fields for other fields description.

Usage:

const data = [
    {
      amount: 100,
      recipient: '3P23fi1qfVw6RVDn4CH2a5nNouEtWNQ4THs',
    },
    {
      amount: 200,
      recipient: 'alias:T:merry',
    },
]

const [tx] = await signer
  .massTransfer(data)
  .broadcast();

reissue

Creates reissue transaction.

reissue(data: {
  assetId: 'string',
  quantity: LONG,
  reissuable: boolean,
})

Parameters:

Field name Default value Description
assetId* Base58-encoded ID of the asset to reissue
quantity* Amount of asset multiplied by 10^decimals to reissue
reissuable* true – asset reissue is possible.
false — asset reissue is not possible

* Required field

See Common fields for other fields description.

Usage:

const data = {
  assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx'
  quantity: 100000000000,
  reissuable: true,
}

const [tx] = await signer
  .reissue(data)
  .broadcast();

setAssetScript

Creates set asset script transaction.

setAssetScript(data: {
  assetId: 'string',
  script: 'string',
})

Parameters:

Field name Default value Description
assetId* Base58-encoded ID of the asset
script Base64-encoded script (with base64: prefix) to be attached to the asset

* Required field

See Common fields for other fields description.

Usage:

const data = {
  assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
  script: 'base64:AwZd0cYf',
}

const [tx] = await signer
  .setAssetScript(data)
  .broadcast();

setScript

Creates set script transaction.

setScript(data: {
  script: 'string',
})

Parameters:

Field name Default value Description
script Base64-encoded account script or dApp script (with base64: prefix) to be attached to the user account. null means cancelling the script

See Common fields for other fields description.

Usage:

const data = {
  script: 'base64:AAIDAAAAAAAAAAQIARIAAAAAAAAAAA...',
}

const [tx] = await signer
  .setScript(data)
  .broadcast();

sponsorship

Creates sponsorship transaction.

sponsorship(data: {
    assetId: 'string',
    minSponsoredAssetFee: LONG,
})

Parameters:

Field name Default value Description
assetId* Base58-encoded ID of the asset
minSponsoredAssetFee Required amount of sponsored token to be charged to users (per 0.001 WAVES) multiplied by 10^decimals
* Required field

See Common fields for other fields description.

Usage:

const data = {
  assetId: 'AcrRM9STdBu5PNiFveTCbRFTS8tADhKcsbC2KBp8A4tx',
  minSponsoredAssetFee: 314,
}

const [tx] = await signer
  .sponsorship(data)
  .broadcast();

transfer

Creates transfer transaction.

transfer(data: {
  recipient: 'string',
  amount: LONG,
  assetId: 'string',
  attachment: 'string',
  feeAssetId: 'string',
})

Parameters:

Field name Default value Description
recipient* Base58-encoded address or alias (with alias:T: prefix) of the recipient
amount* Amount of asset multiplied by 10^decimals. For example, decimals of WAVES is 8, so the real amount is multipied by 10^8. { "WAVES": 677728840 } means 6.77728840
assetId WAVES Base58-encoded ID of the asset to transfer. null or omitted field means WAVES
attachment Optional data attached to the transaction. This field is often used to attach a comment to the transaction. The maximum data size is 140 bytes
feeAssetId WAVES Base58-encoded ID of the asset to pay the commission. null or omitted field means WAVES

* Required field

See Common fields for other fields description.

Usage:

const data = {
  recipient: '3P8pGyzZL9AUuFs9YRYPDV3vm73T48ptZxs',
  amount: 10000,
  }

const [tx] = await signer
  .transfer(data)
  .broadcast();

batch

Creates list of transactions.

batch([{
  type: number,
  ... // fields depending on the transaction type
}])

Parameters:

Field name Default value Description
type* Transaction type ID

* Required field

Usage:

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(); // Or broadcast

In this example, sign method returns array of signed transactions in the same order as they are defined in batch.

Others

broadcast

Sends transactions that are already signed to the blockchain.

broadcast(tx,[options])

Returns: Promise of node response. See the POST /transactions/broadcast method description of Node API.

Parameters:

Field name Default value Description
tx* Signed transaction or array of signed transactions
options.chain false [Type: boolean] Send the next transaction only after the previous transaction is put in the blockchain and confirmed
options.confirmations -1 Number of confirmations after that the Promise is resolved:
less than 0 – Promise is resolved when the transaction is put in UTX pool
0 – Promise is resolved when the block that contains the transaction is added to the blockchain
1 – Promise is resolved when the next block is added to the blockchain and so on

* Required field

Usage:

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});

In this example:

  • transfer1 transaction is sent to the node and put in UTX pool.
  • Block with transfer1 and two more blocks are added to the blockchain.
  • transfer2 transaction is sent to the node and put in UTX pool.
  • Block with transfer2 and two more blocks are added to the blockchain.
  • Promise is resolved and you can notify user that his/her transactions are confirmed.

setProvider

Specifies a Provider that is used to sign transactions. See Provider Interface to find out the provider requirements.

setProvider(provider);

Parameters:

Field name Default value Description
provider* Object that features Provider interface

* Required field

Usage:

signer.setProvider(new Provider());

waitTxConfirm

Waits for the transaction to appear in the blockchain.

waitTxConfirm(tx, confirmations)

Parameters:

Field name Default value Description
tx* Transaction or array transactions that are sent to the blockchain
confirmations* Number of blocks added to the blockchain after the block that contains the transaction

* Required field

Usage:

const [tx] = await signer
  .transfer({amount: 10000000, recipient: 'alias:T:merry'})
  .broadcast();

signer.waitTxConfirm(tx, 1).then((tx) => {
  // Tx have one confirmation
}});

Provider Interface

Provider should feature the following interface:

interface IProvider {

    /**
     * Sets connection to Waves node
     * @param options
     */
    connect(options: {NODE_URL: string, NETWORK_BYTE: number}): Promise<void>;

    /**
     * Authenticates user with his/her account
     */
    login(): Promise<{addres: string, publicKey: string}>;

    /**
     * Logs user out
     */
    logout(): Promise<void>;

    /**
     * Signs transactions in array
     * @param list
     */
    sign(list: Array<TTransactionParamWithType>): Promise<Array<TTransactionWithProofs<TLong> & IWithId>>;
}