# Sign transactions and orders in MetaMask
MetaMask is a browser extension that provides a cryptocurrency wallet and a way to interact with decentralized applications.
To enable MetaMask users to perform actions on the Waves blockchain, the Waves protocol added:
- support for Ethereum-like transactions,
- support for ECDSA signed orders in Exchange transactions.
As a result, MetaMask users are now able to:
- transfer tokens: both native WAVES token and custom tokens;
- invoke a dApp script;
- sign an exchange order.
Application developers can use Signer library together with ProviderMetamask to sign and send transactions on behalf of the MetaMask user.
MetaMask support does not imply interaction with other blockchains.
MetaMask support is enabled by feature #17 “Ride V6, MetaMask support”.
# User Address
The address of a MetaMask user consists of 20 bytes. A Waves address also contains 20 significant bytes, with addition of a prefix that is the same for all addresses of the blockchain network and a checksum (see also Address Binary Format). So, the address of the MetaMask user can be converted to Waves format and vice versa: the basis is the same 20 bytes.
⚠️ An account created in MetaMask cannot be moved to a Waves wallet application (WX Network, Keeper Wallet or other), and, conversely, an account from the Waves wallet cannot be moved to MetaMask. MetaMask and Waves use different cryptographic algorithms, so the same seed phrase will result in different accounts with different addresses. There is no way to get a Waves seed phrase from a MetaMask seed phrase so that it results in the same address, and vice versa.
In UIs, the MetaMask user address is represented in HEX encoding, and the Waves address in base58. To convert the address from one format to another, use:
- Waves Explorer for Mainnet, Testnet, and Stagenet.
wavesAddress2eth
andethAddress2waves
functions of node-api-js library.
# Connect to Waves Network
A Waves node provides RPC API functions required for using MetaMask.
MetaMask can be connected to the Waves network manually or programmatically.
To connect manually, a user selects “Custom RPC” in the list of networks and specifies the connection parameters:
- Network Name: Waves, Waves Testnet, or Waves Stagenet. More about blockchain networks
- New RPC URL: the URL of a Waves node with an open RPC API, for example, the URL of the pool of public nodes:
- for Mainnet:
https://nodes.wavesnodes.com/eth
- for Testnet:
https://nodes-testnet.wavesnodes.com/eth
- for Stagenet:
https://nodes-stagenet.wavesnodes.com/eth
- for Mainnet:
- Chain ID: 87 for Mainnet, 84 for Testnet, 83 for Stagenet.
- Currency Symbol: WAVES.
To connect programmatically, a web app can use the Signer library with ProviderMetamask:
- The app calls the
login()
function. - Signer calls the corresponding function of ProviderMetamask, and ProviderMetamask calls the MetaMask API.
- MetaMask opens a window where the user confirms the connection to the network.
- After receiving the confirmation, MetaMask creates the connection and returns the address of the user.
As a result, MetaMask displays the Waves network as available, and the login()
function returns the user address in Waves format.
For a programmatic connection example, see the MetaMask Usage Examples below.
# Incoming transfer
Users of Waves wallets such as Keeper Wallet, WX Network, WavesFX and others (developed by third-party teams from the community) can transfer tokens to a MetaMask user. Some wallets only support Waves addresses, so you should first convert the recipient address from the MetaMask representation to the Waves format. As a result, a regular Transfer transaction is created.
The balance of WAVES native token is displayed in MetaMask automatically when the Waves network is connected. To display the balance for a custom token, the user should specify the Token Contract Address that is the first 20 bytes of the token ID, HEX encoded. To convert the token ID from one format to another, the user can use Waves Explorer for Mainnet, Testnet, and Stagenet.
# Script Invocation
A web app can invoke a dApp script on behalf of a MetaMask user, using the Signer library with ProviderMetamask:
- The app builds and sends the Invoke Script transaction using the
invoke({...}).broadcast()
function. - Signer calls the corresponding ProviderMetamask function, and ProviderMetamask calls the MetaMask API.
- MetaMask opens a window where the user can view the details of the transaction, confirm it or reject.
- Having received the user's confirmation, MetaMask generates the ECDSA signature of the transaction and sends the signed transaction to a Waves node via the RPC API.
- MetaMask displays the transaction status.
Notes:
- MetaMask does not support signing a transaction without broadcasting it, so the
sign()
function of Signer should not be used. - Waves node does not support transaction speeding up or cancellation and only processes the original transaction.
For an example of invoking the script, see the MetaMask Usage Examples below.
# Outgoing Transfer
To transfer a token from MetaMask wallet manually, a user should do the following:
- Connect the Waves network (see above).
- The balance of WAVES is displayed automatically. To add a balance display for a custom token, the user should specify the Token Contract Address that is the first 20 bytes of the token ID, HEX encoded.
- Transfer the token to another address. The address should be specified in the MetaMask representation.
MetaMask creates the Ethereum-like transaction, signs it with the user's private key, and sends the transaction to the Waves node.
To convert the recipient's address and the token ID to the MetaMask representation, the user can use Waves Explorer for Mainnet, Testnet, and Stagenet.
A web application can transfer any Waves-based token on behalf of a MetaMask user, using Signer with ProviderMetamask. To do this, the app builds and sends the Transfer transaction using the transfer({...}).broadcast()
function. Further processing of the transaction is similar to a script invocation described above.
# Ethereum-like Transaction Features
- Transaction cannot be sent from a smart account or dApp, since a MetaMask user can only transfer tokens and invoke dApp scripts and cannot assign a script to their account.
- Sponsored fee is not available: the transaction fee can only be specified in WAVES.
See also Ethereum-like Transaction Binary Format.
# Support in Ride
If an Ethereum-like transaction invokes a dApp script, the Invocation structure that is available to the callable function contains:
- in the
caller
andoriginCaller
fields: the sender's address in Waves format (26 bytes), - in the
callerPublicKey
andoriginCallerPublicKey
fields: the public key of MetaMask user (64 bytes).
If an Ethereum-like transaction is verified by an asset script, the transaction is interpreted as TransferTransaction or InvokeScriptTransaction:
- the
sender
field contains the sender's address in Waves format (26 bytes), - the
senderPublicKey
field contains the public key of MetaMask user (64 bytes). - the
bodyBytes
field is empty, - the
version
field is 0.
A transaction signature is not available in an asset script.
An Ethereum-like transaction is never verified by a smart account or a dApp script verifier function, since such a transaction cannot be sent from a smart account or dApp.
In Standard library version 6:
- The addressFromPublicKey function accepts both a Waves account public key (32 bytes) and a MetaMask account public key (64 bytes) and returns an address in the Waves format (26 bytes).
- The transferTransactionById function returns an Ethereum-like transaction by its ID if the transaction is interpreted as a Transfer transaction. The
proofs
array contains 8 empty values.
# Exchange Order
In an Exchange transaction one of the orders (or both) may have an ECDSA signature. ECDSA signatures are only supported in version 4 orders.
The Signer library does not support signing an order, and you should call signOrder()
function of ProviderMetamask directly.
The app calls the
signOrder()
function of ProviderMetamask passing order parameters.• Asset IDs should be specified in Waves format: 32 bytes in base58; for WAVES, asset ID should be
WAVES
.•
senderPublicKey
must be omitted.ProviderMetamask passes an order to MetaMask as a data structure according to EIP-712.
MetaMask opens a window where the user can see order details, confirm it or reject.
MetaMask returns the ECDSA signature for this data structure.
The app passes the signed order to the matcher.
The matcher executes orders and creates Exchange transactions.
For an example of signing an order, see the MetaMask Usage Examples below.
# Message
A web app can request a signature of an arbitrary string on behalf of a MetaMask user, using the signMessage('...')
function of Signer. ProviderMetamask calls signTypedData
version 4 function of MetaMask API and passes the following structure as an argument:
[
{
"types": {
"EIP712Domain": [
{
"name": "chainId",
"type" :"uint256"
},
],
"Message": [
{
"name": "text",
"type": "string"
}
]
},
"domain": {
"chainId": 87
},
"primaryType": "Message",
"message": {
"text": "some_custom_message"
}
}
]
The chainId
is 87 for Mainnet, 84 for Testnet, and 83 for Stagenet.
To verify the signature, recover the user address from the signature and signed data using the recoverTypedSignature
version 4 function and compare the address to the expected one. See example in the signMessage section of the Signer documentation.
# MetaMask Usage Examples
# Invoke Script
You can see an example of connecting to the Waves network and signing an Invoke Script transaction in the Waves Dapp Ui.
Paste the address of any dApp, for example, 3N62UHvyvvdresjwfsmW4UX2ffDjcDPAkbn on Testnet or 3MRuzZVauiiX2DGwNyP8Tv7idDGUy1VG5bJ on Stagenet.
Click Sign In and select Sign in with Metamask. In MetaMask, confirm the connection to the network. Waves Dapp Ui by default displays the user address in the Waves format, and the and buttons switch the address format.
To get WAVES to pay transaction fees on Testnet or Stagenet, copy the address in Waves format and use Testnet Faucet or Stagenet Faucet.
Specify the callable function arguments and payments (if necessary). Confirm the transaction in MetaMask. The transaction status is displayed in MetaMask on the Activity tab with a slight delay.
The transaction link displayed by MetaMask opens the transaction page in Waves Explorer.
Example code is given in the ProviderMetamask documentation. Install ProviderMetamask and the latest version of Signer for your app.
# Sign Order
You can see an example of order signing on the Signer test page.
In the page settings, select the Waves network: Mainnet, Testnet, or Stagenet. Then click Login via Metamask. In the Order field fill in the order parameters and click Sign. In MetaMask, allow access to your public key, then confirm the data signing. The order signature will appear on the Dapp test page in the sign field.
Example code is given in ProviderMetamask documentation.
# Sign Message
You can see an example of message signing on the Signer test.
In the page settings, select the Waves network: Mainnet, Testnet, or Stagenet. In the Message field paste a string click Sign. In MetaMask, allow access to your public key, then confirm the data signing. The message signature will appear on the Dapp test page in the sign field.