waves_logo Docs
  • Ride Programming Language
    Ride Programming Language
  • Getting Started
    Getting Started
  • Syntax Basics
    • Directives
      Directives
    • Definition
      Definition
    • Expression
      Expression
    • Variable
      Variable
    • Function
      Function
    • Exception
      Exception
    • Comment
      Comment
    Syntax Basics
  • Script Types
    • dApp Script
      • Annotations
        Annotations
      • Callable Function
        Callable Function
      • Verifier Function
        Verifier Function
      dApp Script
    • Account Script
      Account Script
    • Asset Script
      Asset Script
    Script Types
  • Standard Library
    Standard Library
  • Data types
    • Any
      Any
    • BigInt
      BigInt
    • Boolean
      Boolean
    • ByteVector
      ByteVector
    • Int
      Int
    • String
      String
    • Unit
      Unit
    • List
      List
    • Tuple
      Tuple
    • Union
      Union
    Data types
  • Structures
    • Script Actions
      • BinaryEntry
        BinaryEntry
      • BooleanEntry
        BooleanEntry
      • Burn
        Burn
      • DeleteEntry
        DeleteEntry
      • IntegerEntry
        IntegerEntry
      • Issue
        Issue
      • Lease
        Lease
      • LeaseCancel
        LeaseCancel
      • Reissue
        Reissue
      • ScriptTransfer
        ScriptTransfer
      • SponsorFee
        SponsorFee
      • StringEntry
        StringEntry
      Script Actions
    • Common Structures
      • Address
        Address
      • Alias
        Alias
      • Asset
        Asset
      • AssetPair
        AssetPair
      • AttachedPayment
        AttachedPayment
      • BalanceDetails
        BalanceDetails
      • BlockInfo
        BlockInfo
      • Invocation
        Invocation
      • Order
        Order
      • Transfer
        Transfer
      Common Structures
    • Transaction Structures
      • BurnTransaction
        BurnTransaction
      • CreateAliasTransaction
        CreateAliasTransaction
      • DataTransaction
        DataTransaction
      • ExchangeTransaction
        ExchangeTransaction
      • GenesisTransaction
        GenesisTransaction
      • InvokeScriptTransaction
        InvokeScriptTransaction
      • IssueTransaction
        IssueTransaction
      • LeaseCancelTransaction
        LeaseCancelTransaction
      • LeaseTransaction
        LeaseTransaction
      • MassTransferTransaction
        MassTransferTransaction
      • ReissueTransaction
        ReissueTransaction
      • SetAssetScriptTransaction
        SetAssetScriptTransaction
      • SetScriptTransaction
        SetScriptTransaction
      • SponsorFeeTransaction
        SponsorFeeTransaction
      • TransferTransaction
        TransferTransaction
      • UpdateAssetInfoTransaction
        UpdateAssetInfoTransaction
      Transaction Structures
    Structures
  • Built-in Variables
    Built-in Variables
  • Built-in Functions
    • Account Data Storage Functions
      Account Data Storage Functions
    • Blockchain Functions
      Blockchain Functions
    • Byte Array Functions
      Byte Array Functions
    • Converting Functions
      Converting Functions
    • dApp-to-dApp Invocation Function
      dApp-to-dApp Invocation Function
    • Data Transaction Functions
      Data Transaction Functions
    • Decoding Functions
      Decoding Functions
    • Encoding Functions
      Encoding Functions
    • Exception Functions
      Exception Functions
    • Hashing Functions
      Hashing Functions
    • List Functions
      List Functions
    • Math Functions
      Math Functions
    • String Functions
      String Functions
    • Union Functions
      Union Functions
    • Verification Functions
      Verification Functions
    Built-in Functions
  • Operators
    Operators
  • match ... case: Pattern Matching
    match ... case: Pattern Matching
  • Iterations with FOLD<N>
    Iterations with FOLD<N>
  • dApp-to-dApp Invocation
    dApp-to-dApp Invocation
  • Limitations
    • Complexity
      Complexity
    • Data Weight
      Data Weight
    Limitations
  • Previous Versions
    • Version 5
      • Callable Function
        Callable Function
      • Data types
        • Any
          Any
        • BigInt
          BigInt
        • Boolean
          Boolean
        • ByteVector
          ByteVector
        • Int
          Int
        • String
          String
        • Unit
          Unit
        • List
          List
        • Tuple
          Tuple
        • Union
          Union
        Data types
      • Structures
        • Script Actions
          • BinaryEntry
            BinaryEntry
          • BooleanEntry
            BooleanEntry
          • Burn
            Burn
          • DeleteEntry
            DeleteEntry
          • IntegerEntry
            IntegerEntry
          • Issue
            Issue
          • Lease
            Lease
          • LeaseCancel
            LeaseCancel
          • Reissue
            Reissue
          • ScriptTransfer
            ScriptTransfer
          • SponsorFee
            SponsorFee
          • StringEntry
            StringEntry
          Script Actions
        • Common Structures
          • Address
            Address
          • Alias
            Alias
          • Asset
            Asset
          • AssetPair
            AssetPair
          • AttachedPayment
            AttachedPayment
          • BalanceDetails
            BalanceDetails
          • BlockInfo
            BlockInfo
          • Invocation
            Invocation
          • Order
            Order
          • Transfer
            Transfer
          Common Structures
        • Transaction Structures
          • BurnTransaction
            BurnTransaction
          • CreateAliasTransaction
            CreateAliasTransaction
          • DataTransaction
            DataTransaction
          • ExchangeTransaction
            ExchangeTransaction
          • GenesisTransaction
            GenesisTransaction
          • InvokeScriptTransaction
            InvokeScriptTransaction
          • IssueTransaction
            IssueTransaction
          • LeaseCancelTransaction
            LeaseCancelTransaction
          • LeaseTransaction
            LeaseTransaction
          • MassTransferTransaction
            MassTransferTransaction
          • ReissueTransaction
            ReissueTransaction
          • SetAssetScriptTransaction
            SetAssetScriptTransaction
          • SetScriptTransaction
            SetScriptTransaction
          • SponsorFeeTransaction
            SponsorFeeTransaction
          • TransferTransaction
            TransferTransaction
          • UpdateAssetInfoTransaction
            UpdateAssetInfoTransaction
          Transaction Structures
        Structures
      • Built-in Variables
        Built-in Variables
      • Built-in Functions
        • Account Data Storage Functions
          Account Data Storage Functions
        • Blockchain Functions
          Blockchain Functions
        • Byte Array Functions
          Byte Array Functions
        • Converting Functions
          Converting Functions
        • dApp-to-dApp Invocation Function
          dApp-to-dApp Invocation Function
        • Data Transaction Functions
          Data Transaction Functions
        • Decoding Functions
          Decoding Functions
        • Encoding Functions
          Encoding Functions
        • Exception Functions
          Exception Functions
        • Hashing Functions
          Hashing Functions
        • List Functions
          List Functions
        • Math Functions
          Math Functions
        • String Functions
          String Functions
        • Union Functions
          Union Functions
        • Verification Functions
          Verification Functions
        Built-in Functions
      • Operators
        Operators
      • Limitations
        • Data Weight
          Data Weight
        Limitations
      Version 5
    • Version 4 and 3
      • Callable Function
        Callable Function
      • Data types
        • Boolean
          Boolean
        • ByteVector
          ByteVector
        • Int
          Int
        • String
          String
        • Unit
          Unit
        • List
          List
        • Tuple
          Tuple
        • Union
          Union
        Data types
      • Structures
        • Script Actions
          • BinaryEntry (v4)
            BinaryEntry (v4)
          • BooleanEntry (v4)
            BooleanEntry (v4)
          • Burn (v4)
            Burn (v4)
          • DataEntry (v3)
            DataEntry (v3)
          • DeleteEntry (v4)
            DeleteEntry (v4)
          • IntegerEntry (v4)
            IntegerEntry (v4)
          • Issue (v4)
            Issue (v4)
          • Reissue (v4)
            Reissue (v4)
          • ScriptTransfer (v3 and v4)
            ScriptTransfer (v3 and v4)
          • SponsorFee (v4)
            SponsorFee (v4)
          • StringEntry (v4)
            StringEntry (v4)
          Script Actions
        • Script Results (v3)
          • ScriptResult
            ScriptResult
          • TransferSet
            TransferSet
          • WriteSet
            WriteSet
          Script Results (v3)
        • Common Structures
          • Address
            Address
          • Alias
            Alias
          • Asset
            Asset
          • AssetPair
            AssetPair
          • AttachedPayment
            AttachedPayment
          • BalanceDetails
            BalanceDetails
          • BlockInfo
            BlockInfo
          • Invocation
            Invocation
          • Order
            Order
          • Transfer
            Transfer
          Common Structures
        • Transaction Structures
          • BurnTransaction
            BurnTransaction
          • CreateAliasTransaction
            CreateAliasTransaction
          • DataTransaction
            DataTransaction
          • ExchangeTransaction
            ExchangeTransaction
          • GenesisTransaction
            GenesisTransaction
          • InvokeScriptTransaction
            InvokeScriptTransaction
          • IssueTransaction
            IssueTransaction
          • LeaseCancelTransaction
            LeaseCancelTransaction
          • LeaseTransaction
            LeaseTransaction
          • MassTransferTransaction
            MassTransferTransaction
          • ReissueTransaction
            ReissueTransaction
          • SetAssetScriptTransaction
            SetAssetScriptTransaction
          • SetScriptTransaction
            SetScriptTransaction
          • SponsorFeeTransaction
            SponsorFeeTransaction
          • TransferTransaction
            TransferTransaction
          • UpdateAssetInfoTransaction
            UpdateAssetInfoTransaction
          Transaction Structures
        Structures
      • Built-in Variables
        Built-in Variables
      • Built-in Functions
        • Account Data Storage Functions
          Account Data Storage Functions
        • Blockchain Functions
          Blockchain Functions
        • Byte Array Functions
          Byte Array Functions
        • Converting Functions
          Converting Functions
        • Data Transaction Functions
          Data Transaction Functions
        • Decoding Functions
          Decoding Functions
        • Encoding Functions
          Encoding Functions
        • Exception Functions
          Exception Functions
        • Hashing Functions
          Hashing Functions
        • List Functions
          List Functions
        • Math Functions
          Math Functions
        • String Functions
          String Functions
        • Union Functions
          Union Functions
        • Verification Functions
          Verification Functions
        Built-in Functions
      • Operators
        Operators
      • Limitations
        • Data Weight
          Data Weight
        Limitations
      Version 4 and 3
    Previous Versions
  • Import Libraries
    Import Libraries
  • Ride Components
    Ride Components
      • English
      • Русский
      On this page
        • Introduction
        • Overview
        • “Hello world!”
        • Blockchain
        • Comments
        • Directives
        • Variables
        • Functions
        • Basic types
        • Special types
        • Data Reading Functions
        • If
        • Exceptions
        • Predefined Data Structures
        • Loops With FOLD<N>
        • Annotations
        • Verifier Function
        • Callable Function
        • Testing and Tools
        • Enjoy the Ride!
      waves_logo Docs

          # Getting started

          # Introduction

          Ride is a purpose-designed programming language for smart contracts on the Waves blockchain. It was created to address many of the most serious shortcomings of other popular smart contract languages. The overall idea was to offer a straightforward functional language for dApp development on the Waves blockchain.

          Ride is easy to learn, especially for beginning developers. This article gives a comprehensive introduction to Ride, along with examples and further tools and resources.

          # Overview

          Ride is a statically-typed, lazy, functional, expression-based compiled programming language. It is designed for building developer-friendly decentralized applications (dApps).

          Ride is not Turing Complete and its execution engine (virtual machine) doesn’t have any concept of loops. Also, there are a number of limitations by design, helping to ensure execution is secure and straightforward. However, we recognize that iterations are necessary and have implemented them as FOLD macros (see below). One of the key features is that the execution cost is always predictable and known in advance.

          Despite being simple to use, however, Ride is powerful and offers wide-ranging functionality to developers. It’s broadly based on Scala and is also influenced by F# and the functional paradigm.

          Ride is simple and concise. It will take around an hour to read this brochure, after which you will know everything about the Ride and opportunities that it gives for dApps development.

          # “Hello world!”

          Let’s start with a familiar example:

          func say() = {
            "Hello world!"
          }
          

          Functions in Ride are declared with func (see further below). Functions do have return types, this is inferred automatically by the compiler, so you don't have to declare them. In the case above the function say returns the string Hello World!. There is no return statement in the language because Ride is expression-based (everything is an expression), and the last statement is a result of the function.

          # Blockchain

          Ride was created specifically for execution within a blockchain environment and is optimised for this purpose. Because the blockchain is a shared ledger, located on many computers all around the world, it works a little differently to conventional programming languages.

          Since Ride is designed to be used inside the blockchain, there is no way to access the filesystem or display anything in the console. Instead, Ride functions can read data from the blockchain and return actions as a result, which can then be applied to the blockchain.

          # Comments

          You can add comments to your code much as you can with other languages such as Python:

          # This is a comment line
          
          # And there is no multiline comments
          
          "Hello world!" # You can write comments like here
          

          # Directives

          Every Ride script should start with directives for the compiler. At the time of publication, there are three types of directive, with different possible values.

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

          STDLIB_VERSION sets the version of the standard library. The latest version currently in production is 8.

          CONTENT_TYPE sets the type of the file you're working on. There are different content types, DAPP and EXPRESSION. The DAPP type allows you to define functions and finish execution with certain actions which result in account balances, asset properties, and entries in the dApp account data storage. The EXPRESSION type should always return a boolean value, since it’s used as a predicate for transaction validation.

          SCRIPT_TYPE sets the entity type we want to add to the script to change its default behavior. Ride scripts can be attached to either an ACCOUNT or ASSET.

          Not all combinations of directives are correct. The example below won’t work, because DAPP content type is allowed only for accounts, while EXPRESSION type is allowed for assets and accounts.

          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ASSET #-} # dApp content type is not allowed for an asset
          

          # Variables

          Variables are declared and initialized with the let keyword.

          let a = "Bob"
          let b = 1
          

          All variables in Ride are immutable. This means you cannot change the value of a variable after declaration.

          Ride is strongly typed and the variable's type is inferred from the value on the right hand side.

          Ride allows you to define variables globally, inside any function, or even inside a variable definition.

          func lazyIsGood() = {
            let a = "Bob"
            let b = {
               let x = 1
               “Alice”
              }  
            true
          }
          

          The function above will compile and return true as a result, but variable a won't be evaluated because initialization via let is lazy: unused variables are not evaluated. For strict (eager) initialization, use the strict keyword.

          # Functions

          Functions in Ride can only be used after they are declared.

          func greet(name: String) = {
            "Hello, " + name
          }
          
          func add(a: Int, b: Int) = {
            func m(a:Int) = a
            m(a) + b
          }
          

          The type (Int, String, etc) comes after the argument’s name.

          As in many other languages, functions should not be overloaded. It helps to keep the code simple, readable and maintainable.

          func calc() = {
            42
          }
          
          func do() = { 
            let a = calc()
            true
          }
          

          The calc function will not be called either, because variable a is unused.

          Unlike most languages, variable shadowing is not allowed. Declaring a variable with a name that is already used in a parent scope will result in a compilation error.

          Functions should be defined before they are used.

          Functions can be invoked in prefix and postfix order:

          let list = [1, 2, 3]
          let a1 = list.size()
          let a2 = size(list)
          
          let b1 = getInteger(this, “key”)
          let b2 = this.getInteger(“key”)
          

          In these examples a1 is the same as a2 and b1 is the same as b2.

          # Basic types

          The main basic types and examples are listed below:

          Boolean    #   true
          String     #   "Hey"
          Int        #   1610
          ByteVector #   base58'...', base64'...', base16'...', fromBase58String("...") etc.
          

          We will explore Strings and special types further below.

          # Strings

          let name = "Bob"   # use "double" quotes only
          let coolName = name + " is cool!" # string concatenation by + sign
          
          name.indexOf("o")  # 1
          

          Like other data structures in Ride, strings are immutable. String data is encoded using UTF-8.

          Only double quotes can be used to denote strings. Strings are immutable, just like all other types. This means that the substring function is very efficient: no copying is performed and no extra allocations are required.

          All operators in Ride must have values of the same type on both sides. The following code will not compile because age is an int:

          let age = 21
          "Bob is " + age # won't compile
          

          To make it work we have to convert age to string:

          let age = 21
          "Alice is " + age.toString() # will work!
          

          # Special types

          Ride has few core types, which operate much as they do in Scala.

          # Unit

          There is no null in Ride, as is the case in many other languages. Usually, built-in functions return unit value of type unit instead of null.

          "String".indexOf("substring") == unit # true
          

          # Nothing

          Nothing is the 'bottom type' of Ride’s type system. No value can be of type Nothing, but an expression of type Nothing can be used everywhere. In functional languages, this is essential for support for throwing an exception:

          2 + throw() # the expression compiles because
              # there's a defined function +(Int, Int).
                # The type of the second operand is Nothing, 
                # which complies to any required type.
          

          # List

          let list = [16, 10, 1997, "birthday"]       # can contain different data types
          
          let second = list[1]                        # 10 - read second value from the list
          

          List doesn't have any fields, but there are functions and operators in the Standard library that make it easier to work with fields.

          let list = [16, 10, 1997, "birthday"]
          
          let last = list[(list.size() - 1)] # "birthday", postfix call of size() function
          
          let lastAgain = getElement(list, size(list) - 1) # the same as above
          

          .size() function returns the length of a list. Note that it's a read-only value, and it cannot be modified by the user. (Note also that last could be of more than one type, but this is only inferred when the variable is set.)

          let initList = [16, 10]                   # init value
          let newList = cons(1997, initList)        # [1997, 16, 10]
          let newList2 = 1997 :: initList           # [1997, 16, 10]
          let newList2 = initList :+ 1              # [16, 10, 1]
          let newList2 = [4, 8, 15, 16] ++ [23, 42]     # [4 8 15 16 23 42]
          
          • To prepend an element to an existing list, use the cons function or :: operator
          • To append an element, use the :+ operator
          • To concatenate 2 lists, use the ++ operator

          # Tuple

          Tuple is an ordered collection of elements. Elements can be of any type.

          let x=("Hello Waves",42,true)
          let num = x._2                                # 42
          let (a,b,c) = x
          let bool = c                                  # true
          

          # Union Types & Type Matching

          let valueFromBlockchain = getString("3PHHD7dsVqBFnZfUuDPLwbayJiQudQJ9Ngf", "someKey") # Union(String | Unit)
          

          Union types are a very convenient way to work with abstractions. Union(String | Unit) shows that the value is an intersection of these types.

          The simplest example of Union types is given below (please bear in mind that defining custom user types in dApp code will be supported in future versions):

          type Human : { firstName: String, lastName: String, age: Int}
          type Cat : {name: String, age: Int }
          

          Union(Human | Cat) is an object with one field, age, but we can use pattern matching:

          Human | Cat => { age: Int }
          

          Pattern matching is designed to check a value against value type:

            let t = ...               # Cat | Human
            t.age                     # OK
            t.name                    # Compiler error
            let name = match t {      # OK
              case h: Human => h.firstName
              case c: Cat   => c.name
            }
          

          Type matching is a mechanism for:

          let amount = match tx {              # tx is a current outgoing transaction
            case t: TransferTransaction => t.amount
            case m: MassTransferTransaction => m.totalAmount
            case _ => 0
          }
          

          The code above shows an example of type matching. There are different types of transactions in Waves, and depending on the type, the real amount of transferred tokens can be stored in different fields. If a transaction is TransferTransaction or MassTransferTransaction we use the corresponding field, while in all other cases, we will get 0.

          # Data Reading Functions

          let readOrZero = match getInteger(this, "someKey") { # reading data
              case a:Int => a
              case _ => 0
          }
          
          readOrZero + 1
          

          getString returns Union(String | Unit) because while reading data from the blockchain (the key-value data storages of accounts) some key-value pairs may not exist.

          let v = getInteger("3PHHD7dsVqBFnZfUuDPLwbayJiQudQJ9Ngf", "someKey")
          v + 1    # doesn’t compile, forcing a developer to foresee the possibility of non-existing value for the key
          
          v.valueOrErrorMessage(“oops”) +  1 # compiles and executes
          
          let realStringValue2 = getStringValue(this, "someKey")
          

          To get the real type and value from Union use the value function, which will terminate the script in case of unit value. Another option is to use specialized functions like getStringValue, getIntegerValue, etc.

          # If

          let amount = 1610
          if (amount > 42) then "I claim that amount is bigger than 42"
            else if (amount > 100500) then "Too big!"
            else "I claim something else"
          

          if statements are pretty straightforward and similar to most other languages, with an important difference from some: if is an expression, so it must have an else clause (the result is assignable to a variable).

          let a = 16
          let result = if (a > 0) then a / 10 else 0 #
          

          # Exceptions

          throw("Here is exception text")
          

          The throw function will terminate script execution immediately, with the provided text. There is no way to catch thrown exceptions.

          The idea of throw is to stop execution and send useful feedback to the user.

          let a = 12
          if (a != 100) then
            throw ("a is not 100, actual value is " + a.toString())
            else throw("A is 100")
          

          # Predefined Data Structures

          #LET THE HOLY WAR BEGIN

          Ride has many predefined data structures specific to the Waves blockchain, such as: Address, Alias, Invocation, Issue, Lease, ScriptTransfer, StringEntry, ExchangeTransaction, SetScriptTransactions.

          let keyValuePair = StringEntry("someKey", "someStringValue")
          

          For example, StringEntry is a structure which describes a key-value pair with string value, e.g. for an account data storage.

          All structures can be used for type checking, pattern matching and their constructors as well.

          # Loops With FOLD<N>

          Since Ride’s virtual machine doesn’t have any concept of loops, they are implemented at compiler level via the FOLD<N> macro. The macro behaves like the ‘fold’ function in other programming languages, taking the input arguments: collection for iteration, starting values of the accumulator and folding function.

          The important aspect is N - the maximum amount of interactions over collections. This is necessary for maintaining predictable computation costs.

          This code sums the numbers of the array:

          let a = [1, 2, 3, 4, 5]
          func foldFunc(acc: Int, e: Int) = acc + e
          FOLD<5>(a, 0, foldFunc) # returns 15
          

          FOLD<N> can also be used for filtering, mapping, and other operations. Here’s an example for map with reverse:

          let a = [1, 2, 3, 4, 5]
          func foldFunc(acc: List[Int], e: Int) = (e + 1) :: acc
          FOLD<5>(a, [], foldFunc) # returns [6, 5, 4, 3, 2]
          

          # Annotations

          Functions can be without annotations, or with @Callable or @Verifier annotations. Annotated function are used only in scripts of type DAPP.

          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ACCOUNT #-}
          
          func getPayment(i: Invocation) = {
            if (size(i.payments) == 0)
              then throw("Payment must be attached")
              else {
                let pmt = i.payments[0]
                if (isDefined(pmt.assetId))
                  then throw("This function accepts WAVES tokens only")
                  else pmt.amount
              }
          }
          
          @Callable(i)
          func pay() = {
            let amount = getPayment(i)
            (
              [
                IntegerEntry(toBase58String(i.caller.bytes), amount)
              ],
              unit
            )
          }
          

          Annotations can bind some values to the function. In the example above, variable i was bound to the function pay and stored some fields of the invocation (the caller’s public key, address, payments attached to the invocation, fee, transaction ID etc.).

          Functions without annotations are not available from the outside. You can call them only inside other functions.

          # Verifier Function

          @Verifier(tx)
          func verifier() = {
            match tx {
              case ttx: TransferTransaction => ttx.amount <= 100 # can send up to 100 tokens
              case _ => false
            }
          }
          

          A function with the @Verifier annotation sets the rules for outgoing transactions of a decentralized application (dApp). Verifier functions cannot be called from the outside, but they are executed every time an attempt is made to send a transaction from a dApp.

          Verifier functions should always return a Boolean value as a result, depending on which a transaction will be recorded to the blockchain or not.

          Expression scripts (with directive {-# CONTENT_TYPE EXPRESSION #-}) along with functions annotated by @Verifier should always return a boolean value. Depending on that value the transaction will be accepted (in case of true) or rejected (in case of false) by the blockchain.

          @Verifier(tx)
          func verifier() = {
            sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
          }
          

          The Verifier function binds variable tx, which is an object with all fields of the current outgoing transaction.

          A maximum of one @Verifier() function can be defined in each dApp script.

          # Callable Function

          Functions with the @Callable annotation can be called (or invoked) from other accounts: by an Invoke Script transaction or by a dApp.

          A callable function can perform actions: write data to the dApp data storage, transfer tokens from the dApp to other accounts, issue/release/burn tokens, and others. The result of a callable function is a tuple of two elements: a list of structures describing script actions and a value passed to the parent function in case of the dApp-to-dApp invocation.

          @Callable(i)
          func giveAway(age: Int) = {
            (
              [
                ScriptTransfer(i.caller, age, unit),
                IntegerEntry(toBase58String(i.caller.bytes), age)
              ],
              unit
            )
          }
          

          Every caller of giveAway function will receive as many WAVELETs as their age. The ScriptTransfer structure sets the parameters of the token transfer. dApp also will store information about the fact of the transfer in its data storage. The IntegerEntry structure sets the parameters of the entry: key and value.

          # Testing and Tools

          You can try out Ride in REPL both online at https://waves-ide.com/ and on desktop via terminal with surfboard:

          > npm i -g @waves/surfboard
          > surfboard repl
          

          For further development, the following tools and utilities are useful:

          • Visual Studio Code plugin: waves-ride
          • The surfboard tool for compiling Ride smart contracts and running tests: https://github.com/wavesplatform/surfboard
          • Online IDE with examples: https://waves-ide.com/

          Further information about tools

          # Enjoy the Ride!

          Hopefully this article will have given you a good introduction to Ride: a straightforward, secure, powerful programming language for smart contracts and dApps on the Waves blockchain.

          Now you are able to write your own smart contracts, and have all the tools you need to test them before deploying them to the Waves blockchain.

          If you need help learning the basics of the Ride language, you can take the Waves lessons .

          Ride Programming Language
          Syntax Basics
          Ride Programming Language
          Syntax Basics