Hello! In this article, I will show you how to write and deploy a regular dApp on the Waves node. We will look at the necessary tools, methods, and a development example.

The development process for dApps and regular applications is almost identical:
- Writing code
- Writing automated tests
- Launching the application
- Testing
Tools
1. docker for launching the node and Waves Explorer
If you do not want to launch a node, you can skip this step. There is a test and experimental network available. However, without setting up your own node, the testing process may take longer.
- You will constantly need new accounts with test tokens. The test network faucet transfers 10 WAVES every 10 minutes.
- The average block time in the test network is 1 minute, while in the node it is 15 seconds. This is especially noticeable when a transaction requires several confirmations.
- In public test nodes, aggressive caching may occur.
- They may also be temporarily unavailable due to maintenance.
From here on, I will assume you are working with your own node.
2. Command Line Tool Surfboard
- Download and install Node.js using ppa, homebrew, or exe here: .
- Install Surfboard – a tool that will allow you to run tests on the existing node.
npm install -g @waves/surfboard
3. Visual Studio Code Plugin
This step is optional if you are not a fan of IDEs and prefer text editors. All necessary tools are command line utilities. If you use vim, pay attention to the plugin .
Download and install Visual Studio Code:
Open VS Code and install the waves-ride plugin:

Browser extension Waves Keeper:
Done!
Run the node and Waves Explorer
1. Start the node:
docker run -d -p 6869:6869 wavesplatform/waves-private-node
Make sure the node is running through the REST API at :

Swagger REST API interface for the node
2. Start an instance of Waves Explorer:
docker run -d -e API_NODE_URL=http://localhost:6869 -e NODE_LIST=http://localhost:6869 -p 3000:8080 wavesplatform/explorer
Open your browser and navigate to . You will see how quickly a blank chain is built on the local node.

Waves Explorer displays the instance of the local node
Structure of RIDE and the Surfboard tool
Create an empty directory and run the command in it
surfboard init
The command initializes the directory with the project structure, a 'hello world' type application, and tests. If you open this folder with VS Code, you will see:

Surfboard.config.json
- In the folder ./ride/ you will find a single file wallet.ride – the directory where the dApp code is located. We will briefly analyze the dApp in the next section.
- In the folder ./test/ you will find the *.js file. This is where the tests are stored.
- ./surfboard.config.json – the configuration file for running the tests.
Envs – an important section. Each environment is configured as follows:
- The REST API node endpoint that will be used to run the dApp and the CHAIN_ID of the network.
- The secret phrase for the account containing the tokens that will be the sources of your test tokens.
As you can see, surfboard.config.json by default supports multiple environments. The default environment is set (the defaultEnv key is a configurable parameter).
Wallet-demo application
This section is not a manual on the RIDE language. Rather, it's an overview of the application we are deploying and testing to better understand what's happening on the blockchain.
Let's consider the simple Wallet-demo application. Anyone can send tokens to the dApp address. You can only withdraw your WAVES. Two @Callable functions are available through InvokeScriptTransaction:
deposit(), which requires an attached payment in WAVES.withdraw(amount: Int), which returns tokens.
Throughout the dApp lifecycle, the structure (address → amount) will be maintained:
Action
Resulting state
initial
empty
Alice deposits 5 WAVES
alice-address → 500000000
Bob deposits 2 WAVES
alice-address → 500000000
bob-address → 200000000
Bob withdraws 7 WAVES
DENIED!
Alice withdraws 4 WAVES
alice-address → 100000000
bob-address → 200000000
Here’s the code for a complete understanding of the situation:
# In this example multiple accounts can deposit their funds and safely take them back. No one can interfere with this.
# An inner state is maintained as mapping `address=>waves`.
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
@Callable(i)
func deposit() = {
let pmt = extract(i.payment)
if (isDefined(pmt.assetId))
then throw("works with waves only")
else {
let currentKey = toBase58String(i.caller.bytes)
let currentAmount = match getInteger(this, currentKey) {
case a:Int => a
case _ => 0
}
let newAmount = currentAmount + pmt.amount
WriteSet([DataEntry(currentKey, newAmount)])
}
}
@Callable(i)
func withdraw(amount: Int) = {
let currentKey = toBase58String(i.caller.bytes)
let currentAmount = match getInteger(this, currentKey) {
case a:Int => a
case _ => 0
}
let newAmount = currentAmount - amount
if (amount < 0)
then throw("Can't withdraw negative amount")
else if (newAmount < 0)
then throw("Not enough balance")
else ScriptResult(
WriteSet([DataEntry(currentKey, newAmount)]),
TransferSet([ScriptTransfer(i.caller, amount, unit)])
)
}
@Verifier(tx)
func verify() = falseYou can also find example code at .
The VSCode plugin supports continuous compilation while editing the file. Therefore, you can always monitor errors in the PROBLEMS tab.

If you want to use another text editor while compiling the file, use
surfboard compile ride/wallet.ride
This will output a series of base64 compiled RIDE code.
Test script for 'wallet.ride'
Let's take a look at It runs on the JavaScript Mocha framework. There is a 'Before' function and three tests:
- The 'Before' function funds several accounts through MassTransferTransaction, compiles the script, and deploys it to the blockchain.
- 'Can deposit' sends an InvokeScriptTransaction to the network, activating the deposit() function for each of the two accounts.
- 'Can’t withdraw more than was deposited' tests that no one can steal other people's tokens.
- 'Can deposit' verifies that withdrawals are processed correctly.
Running tests with Surfboard and analyzing results in Waves Explorer
To run the test, execute
surfboard test
If you have several scenarios (for example, you need a separate deployment script), you can run
surfboard test my-scenario.js
Surfboard will gather test files in the .\/test\/ folder and execute the script on the node configured in surfboard.config.json. After a few seconds, you will see something like this:
wallet test suite
Generating accounts with nonce: ce8d86ee
Account generated: foofoofoofoofoofoofoofoofoofoofoo#ce8d86ee - 3M763WgwDhmry95XzafZedf7WoBf5ixMwhX
Account generated: barbarbarbarbarbarbarbarbarbar#ce8d86ee - 3MAi9KhwnaAk5HSHmYPjLRdpCAnsSFpoY2v
Account generated: wallet#ce8d86ee - 3M5r6XYMZPUsRhxbwYf1ypaTB6MNs2Yo1Gb
Accounts successfully funded
Script has been set
√ Can deposit (4385ms)
√ Cannot withdraw more than was deposited
√ Can withdraw (108ms)
3 passing (15s)
Hooray! The tests have passed. Now let's take a look at what happens when using Waves Explorer: checking blocks or input one of the above addresses into the search (for example, the corresponding wallet#. There you can find the transaction history, dApp status, and the decompiled binary file.

Waves Explorer. The application that has just been deployed.
A few tips for Surfboard:
1. To test in the testnet environment, use:
surfboard test --env=testnet
2. If you want to see JSON versions of transactions and how they are processed by the node, run the test with -v (which means 'verbose'):
surfboard test -v
Using applications with Waves Keeper
1. Set up Waves Keeper to work:

Configuring Waves Keeper to work with a local node
2. Import the secret phrase with tokens for the network? For simplicity, use your node's initial seed: waves private node seed with waves tokens. Address: 3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF.
3. You can run a single-page serverless application yourself using npm. Or go to an existing one:
4. Enter the wallet address from the test run (highlighted above) into the dApp address text field
5. Enter a small amount in the 'Deposit' field and click the button:

Waves Keeper requests permission to sign InvokeScriptTransaction with a payment of 10 WAVES.
6. Confirm the transaction:

The transaction has been created and is being broadcast to the network. Its ID can now be seen
7. Monitor the transaction using Waves Explorer. Enter the ID into the search field

Conclusions and additional information
We have reviewed the development, testing, deployment, and usage tools for simple dApps on the Waves Platform:
- RIDE Language
- VS Code Editor
- Waves Explorer
- Surfboard
- Waves Keeper
Links for those who want to continue learning RIDE:
Continue to explore RIDE and create your first dApp!
TL;DR:
Source: habr.com
