waves_logo Docs
  • Overview
    Overview
  • How-to Guides
    • Reading Blockchain Data
      Reading Blockchain Data
    • Creating & Broadcasting Transactions
      Creating & Broadcasting Transactions
    • Tokenization
      Tokenization
    • Airdrop
      Airdrop
    • Payments
      Payments
    • Exchange Tokens
      Exchange Tokens
    • Simple Voting
      Simple Voting
    • List as argument
      List as argument
    How-to Guides
  • Waves Smart Contracts
    Waves Smart Contracts
  • dApp
    • Creating & Launching dApp
      Creating & Launching dApp
    dApp
  • Smart Account
    • Creating smart account
      Creating smart account
    • Creating and deploying a script manually
      Creating and deploying a script manually
    • Video tutorials
      • Introduction to the Waves blockchain, Waves Smart Accounts and Waves Smart Assets
        Introduction to the Waves blockchain, Waves Smart Accounts and Waves Smart Assets
      • Waves Smart Account with multisignature
        Waves Smart Account with multisignature
      • Waves Smart Account with escrow service
        Waves Smart Account with escrow service
      • Creating multisignature account via Waves IDE tools
        Creating multisignature account via Waves IDE tools
      • Creating multisignature account via Waves Client
        Creating multisignature account via Waves Client
      • Waves console explained
        Waves console explained
      Video tutorials
    Smart Account
  • Smart Asset
    Smart Asset
  • Developer Tools
    • Waves IDE
      Waves IDE
    • Visual Studio Code Extension
      Visual Studio Code Extension
    • Surfboard
      Surfboard
    • Ride REPL
      Ride REPL
    Developer Tools
  • Signer ◆
    Signer ◆
  • Waves API
    • Data Service API
      Data Service API
    • Node REST API
      Node REST API
    • Node gRPC Server
      Node gRPC Server
    • Blockchain Updates
      Blockchain Updates
    Waves API
  • Client Libraries
    • Waves C#
      • Install SDK
        Install SDK
      • Run Code Sample
        • Send Transactions
          Send Transactions
        • Use Crypto Utilities
          Use Crypto Utilities
        • Interact With Node
          Interact With Node
        • Set Up Smart Contracts
          Set Up Smart Contracts
        Run Code Sample
      Waves C#
    • Gowaves
      • Install SDK
        Install SDK
      • Run Code Sample
        • Send Transactions
          Send Transactions
        • Use Crypto Utilities
          Use Crypto Utilities
        • Interact With Node
          Interact With Node
        • Set Up Smart Contracts
          Set Up Smart Contracts
        Run Code Sample
      Gowaves
    • WavesJ
      • Install SDK
        Install SDK
      WavesJ
    • Ts-lib-crypto
      • Install SDK
        Install SDK
      Ts-lib-crypto
    • Waves-PHP
      • Install SDK
        Install SDK
      Waves-PHP
    • PyWaves-CE
      • Install SDK
        Install SDK
      PyWaves-CE
    • Waves-rust
      • Install SDK
        Install SDK
      Waves-rust
    Client Libraries
      • English
      • Русский
      On this page
        • Roadmap
        • Step 1. Create dApp Account
        • Step 2. Write dApp Script
        • Step 3. Assign Script to Account
        • Step 4. Test Script
        • Step 5. Release the real-world application
        • What's next
      waves_logo Docs

          # How to Create and Launch dApp: Complete Tutorial

          This tutorial provides steps to develop and launch sample dApp based on Waves blockchain. You can then repeat the steps to create more advanced dApps.

          The sample dApp you'll create is the Waves Magic 8 Ball application that generates pseudorandom answers. You will use Waves IDE to develop and test dApp and then use JavaScript to deploy the web app that calls the dApp functions.

          Learn more about dApp features

          # Roadmap

          1. Create a dApp account.
          2. Write a dApp script.
          3. Assign the script to the dApp account.
          4. Test the script.
          5. Release a real-world application.

          # Step 1. Create dApp Account

          1. Open Waves IDE .

          2. Click and make sure that Testnet is selected.

          3. Click Add account → Generate new account.

          4. Click Show seed and private key and backup the seed phrase to a secure location. You will need the seed phrase to restore access to the account.

          5. Top up account balance. It's free on Testnet.

            • Copy address: click account name and then click .

            • Go to Waves Faucet , paste address, and click Request WAVES.

          # Step 2. Write dApp Script

          1. Click and select dApp script.
          2. Replace the automatically generated code with your script.

          The file is saved in Waves IDE automatically.

          You can copy Waves Magic 8 Ball script from IDE library: Library → ride4dapps → 8ball → ride → 8ball.ride.

          Script code
          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ACCOUNT #-}
          
          # Determine the number and list of responses
          let answersCount = 20
          let answers = 
            ["It is certain.",
            "It is decidedly so.",
            "Without a doubt.",
            "Yes - definitely.",
            "You may rely on it.",
            "As I see it, yes.",
            "Most likely.",
            "Outlook good.",
            "Yes.",
            "Signs point to yes.",
            "Reply hazy, try again.",
            "Ask again later.",
            "Better not tell you now.",
            "Cannot predict now.",
            "Concentrate and ask again.",
            "Don't count on it.",
            "My reply is no.",
            "My sources say no.",
            "Outlook not so good.",
            "Very doubtful."]
          
          # Function to generate pseudo-random answers
          func getAnswer(question: String, previousAnswer: String) = {
            let hash = sha256(toBytes(question + previousAnswer))
            let index = toInt(hash)
            answers[index % answersCount]
          }
          
          # Function to get previous response from storage
          func getPreviousAnswer(address: String) = {
            match getString(this, address + "_a") {
              case a: String => a
              case _ => address
            }
          }
          
          # Callable function
          @Callable(i)
          func tellme(question: String) = {
            # Get the address of the user who calls the contract
            let callerAddress = i.caller.toString()
            # Get a pseudo-random answer
            let answer = getAnswer(question, getPreviousAnswer(callerAddress))
            # Write data to the storage
            [
              StringEntry(callerAddress + "_q", question),
              StringEntry(callerAddress + "_a", answer)
            ]
          }
          
          Explanation of the code

          dApp-script should start with directives:

          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ACCOUNT #-}
          

          After directives you can declare variables and auxiliary functions.

          Callable functions should be marked with the @Callable(i) annotation. The i object contains invoke script transaction fields that the callable function can use. In the example we use the i.caller.bytes field that contains address of user account that called the function.

          Callable function result is a set of script actions. In the example, the function performs two StringEntry actions that add or modify a string type record in the dApp data store.

          For more information about the structure of the dApp script, see the Structure of dApp Script.

          # Step 3. Assign Script to Account

          To assign dApp script to the account, send a set script transaction from this account. The fee for the set script transaction is 0.01 WAVES.

          You can send a set script transaction directly from Waves IDE:

          1. Open dApp script and click Deploy.
          2. Click Add sign to sign the transaction. Then click Publish.

          You can check the assigned script in Waves Explorer:

          1. Go to https://wavesexplorer.com/ .
          2. In the top right menu, select Testnet.
          3. Use search bar to find the dApp account by address.
          4. Switch to Script tab.

          Now dApp is ready — users can call dApp functions using invoke script transactions.

          # Step 4. Test Script

          To test the dApp script send an invoke script transaction. The fee for the script invocation starts from 0.005 WAVES and depends on the number of smart assets involved (in this example, smart assets are not used). Fee calculation is described in the Transaction Fee article.

          For manual testing, use Waves Dapp Ui :

          1. Create a test user account in the recommended wallet app, for example:

            • in WX Network for Testnet ,

            • or in the Keeper Wallet browser extension (switch to Testnet before creating the account).

          2. Top up your account balance using Waves Faucet .

          3. In Waves Dapp Ui paste the dApp address.

          4. Click Sign In and connect the test user's wallet.

          5. Set the parameters of the callable function and attach payments, if required.

          Waves Dapp UI

          For running test scripts, use Waves IDE. Test scripts support the following functions:

          • describe and it from mocha library;
          • expect from chai library.
          1. Create a test user account and top up its balance as described in Step 1.

          2. Click and select Test.

          3. Replace the automatically generated code with your script.

            You can copy Waves Magic 8 Ball test from IDE library: Library → ride4dapps → 8ball → tests → 8ball_test.js. Remember to replace the ballAddress value with the address of your dApp.

          4. Click Run full test.

          Test code

          describe('8 ball', () => {
              const ballAddress = "3MxBZbnN8Z8sbYjjL5N3oG5C8nWq9NMeCEm"
              const question = "Test" + Date.now()
              const tx = invokeScript({fee: 500000, dApp: ballAddress, call:{function:"tellme", args:[{"type": "string", "value": question}]}, payment: null})

              it('Tx is mined in block', async function(){
                  await broadcast(tx)
                  await waitForTx(tx.id)
              })

              it('Question is in ball', async function(){
                  await accountDataByKey(address()+"_q", ballAddress)
                      .then(reslove => expect(reslove.value).to.equal(question))
              })
          })

          You can check the result of script execution in Waves Explorer:

          1. Go to https://wavesexplorer.com/ .
          2. In the top right menu, select Testnet.
          3. Use search bar to find the dApp account by address.
          4. Switch to Data tab.

          # Step 5. Release the real-world application

          To release your app:

          • Deploy the wep app that allows user to sign and send an invoke script transaction by simply clicking the button.
          • Add your dApp on Mainnet.
          • Register your application in dApp directories to make it known to as many users as possible!

          # 5.1. Deploy Web App

          To invoke dApp functions on behalf of a real user use Signer TypeScript/JavaScript library. Signer enables signing and broadcasting transactions without asking user's seed phrase or private key.

          Invocation code

          await signer.invoke({
              dApp: ballAddress,
              call: {
                  function: "tellme",
                  args:[{"type": "string", "value": question}]
              }
          }).broadcast();

          Full code on Github

          # 5.2. Add dApp on Mainnet

          1. In Waves IDE click and switch to Mainnet.
          2. Create dApp account on Mainnet as described in Step 1.
          3. Top up account balance to pay the fee for the script setup. See the How to Get WAVES section.
          4. Attach dApp script to the account as described in Step 3.

          dApp on Mainnet will have a different address — remember to change the address in your web app. In addition, replace the node address to https://nodes.wavesnodes.com.

          💡 You can enable sponsorship to make the application free for users and pay the script invocations fees yourself.

          # 5.3. Register on DappRadar

          DappRadar is the leading platform for decentralized application discovery and analysis. Submit your dApp there to promote it.

          # What's next

          Waves public nodes have limitations on the number of requests per second. So when your application becomes popular, we recommend to launch your own node and send invoke script transactions to it.

          dApp
          Smart Account
          dApp
          Smart Account