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
        • 1. How to Create a Script
        • Example of transferring Waves with a bad request
        • Example of transferring Waves with a successful request
      waves_logo Docs

          # Creating and deploying a script manually

          The idea of a Smart Account is the following:

          Before the transaction is submitted to be included in the next block, the account checks if the transaction meets certain requirements, defined in a script. The script is attached to the account so the account can validate every transaction before confirming it.

          In this example, we're going to create and deploy a simple 2 of 2 MultiSig example without using neither Waves Client libraries nor API libraries.

          Example Assumptions:

          1. We assume that we have our own Waves node (if you do not have Waves node, you can implement the example using one of Waves Libraries as shown in this video tutorial using Waves Java Library).
          2. We want to set up a script for a generated account in order to implement the **smart account **idea.
          3. we assume that we have three generated addresses:

          3MxjWXEUcVCeiaEUqNcorB5HxSpLsgJCGxE - Alice's account.

          3MqGVvfgqdqqU6P9mTAsLSxyRoRjrHF18Mf - Bob's account.

          3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X - Shared account.

          # 1. How to Create a Script

          The idea here is to create a script and attach it to the account so this account can :

          1. Check if the transaction meets certain requirements which is defined in the script.
          2. Validate the transaction.
          3. Confirm the transaction and broadcast it to the blockchain network.

          Now let's Start our 2 of 2 MultiSig Example:

          1. Use our IDE to write your script (you can find some script examples there)
          2. For this example we will use the following script: In the first two lines, we defined 2 public keys encoded in base58 for both alice and bob. After that, users gather 2 public keys in proofs[0] and proofs[1]. The account is funded by the team members and after that, when 2 of 3 team members decide to spend money, they provide their signatures in a single transaction. The Smart account script, using sigVerify function, validates these signatures with proofs and if 2 of 2 are valid then the transaction is valid too, else the transaction does not pass to the blockchain.
          let alicePubKey  = base58'Ey6Z9XkWsvG8JZwyxhkTjydRcGp1wg6rbC3AYcxq7Efr'
          let bobPubKey    = base58'5PvhyouzHn2Pcev56oBvwpnsGK5fEu1dA8fM2nJQM4HR'
          
          let aliceSigned  = if(sigVerify(tx.bodyBytes, tx.proofs[0], alicePubKey)) then 1 else 0
          let bobSigned    = if(sigVerify(tx.bodyBytes, tx.proofs[1], bobPubKey  )) then 1 else 0
          aliceSigned + bobSigned == 2
          
          1. Switch to the BINARY tab.

          2. Click on COPY TO CLIPBOARD button. A compiled Base64-encoded script should be copied into your clipboard as shown below (this step will be required later).

          5Xt9H8mHtikSytHF72xAU3NJwDydxXYMMhmWiNVLbYdBRQ3FHXksc8kW8tKFm3fGto1EwTt4YSybEUrpT2yB71hCvUS3WxWfsC4PxU7
          oTGt687w8T195NVeMPUqdWeHT5BwVrsoFkXF5SuMEGTaB4RyP43ygfTCNNdWauiV7guKmSvH3V2dFpK1HvhVPBjG1QafJ63Awp5qLzQ
          orFAbBVxgfqFLk6c99vrHCHpdjjiPv3vMN7FWLFrMPhGZbzBdyqQ8pCy1dkadxdkAytxZ3AUszTM2cfREgh9QjVVtcody7VsxDsbTPv
          uETHgcrk96jY7Pzft2nE7W9VF3EcGXJ7VDSKX5ucVpkZwugJCa4SgAkBGPnCxmUf3RmrAUuWaCQPMPfUyayyWfZ4wDguz74cLuDpmU3
          htVHbcuVQ7KrU55b5w4QFZyLDzHvgXXtCiqMEKFTrepcdy2LjA55D63EUhmQgVA6yqQbmLU6WKFabEsXETBRtzmCqPmGeB4iQXS16rB
          WBMHK214mYRoxdAH3zvKyWQcqndnWETd59mCEGkRjB9UUL6vmCF1ZQCSytdJKgyRhRQ7pzxxa5iL92hGSCRdw7yFWAv77aCV3ujJjqs
          SAtDTKwqmdqJpWtBWYLEy6cfaTTKCQFNH2Lnj2DYgaFRWETGQVQpMMVYFKkk
          

          # 2 How to Attach a Script to Account

          1. Now let's prepare a JSON request to sign a SetScriptTransaction for the shared account with a given script:

            {
             "type": 13,
             "version": 1,
             "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
             "fee": 100000,
             "script": "<script>`"
            }
            

            Note, fee is 100000 - a minimal required fee to deploy your script.

          2. Send it to /transactions/sign:

            $ curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' \
            --header 'X-API-Key: <it is a secret>' \
            -d '{ "type": 13, "version": 1, "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X", "fee": 100000, \
            "script": "<script>" }' 'https://example.org/transactions/sign'
            

            and receive a JSON ready to broadcast:

            {
             "type": 13,
             "id": "8w7yauNiENsJP8oDUpVEfiAzyEzMKoXbJEqS26Ht99mg",
             "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
             "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
             "fee": 100000,
             "timestamp": 1525797758819,
             "proofs": [
               "4Ro4e4UrsVkaFbHtu96qZwHAdf8N4TtpjSGik9kRusmmYKCxicdsEqcgQrYden36nurqhY9EBkTKwD499kAi5rxe"
             ],
             "version": 1,
             "script": "<script>"
            }
            
          3. Then we broadcast a prepared request:

            $ curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' \
            --header 'X-API-Key: <it is a secret>' \
            -d '{ "type": 13, "id": "8w7yauNiENsJP8oDUpVEfiAzyEzMKoXbJEqS26Ht99mg", "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X", \
             "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe", "fee": 100000, "timestamp": 1525797758819, \
             "proofs": [ "4Ro4e4UrsVkaFbHtu96qZwHAdf8N4TtpjSGik9kRusmmYKCxicdsEqcgQrYden36nurqhY9EBkTKwD499kAi5rxe" ], \
             "version": 1, "script": "<script>" }' \
            'https://example.org/transactions/broadcast'
            
          4. And check it was applied:

            $ curl http://example.org/addresses/scriptInfo/3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X
            {
             "address" : "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
             "script" : "<script>",
             "scriptText" : "<scriptText>",
             "complexity" : 27,
             "extraFee" : 400000
            }
            

          where <scriptText> is a String representation of compiled <script> (expression tree)

          Fine! Now we able to make transfers from this account.

          # Example of transferring Waves with a bad request

          **From shared account to another account: **3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj

          {
            "type": 4,
            "id": "B7G5KGorZDNrGZbVJ4bi4bhHKX62SVvf18gopK5pi43o",
            "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
            "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
            "fee": 100000,
            "timestamp": 1525797949015,
            "proofs": [
              "yJKWiny1LtcamWxkxJvuYLxAJoxEnc9QTV4WHDk5D2N2rKsvuJjcobwgo1Mu1yRuPm5BZeYEW1nKaDSkZi7xSo5"
            ],
            "version": 2,
            "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj",
            "assetId": null,
            "feeAssetId": null,
            "amount": 100000,
            "attachment": ""
          }
          

          Let's try:

          $ curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'X-API-Key: <it is a secret>' \
          -d '{ "type": 4, "id": "B7G5KGorZDNrGZbVJ4bi4bhHKX62SVvf18gopK5pi43o", "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X", \
          "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe", "fee": 100000, "timestamp": 1525797949015, \
          "proofs": [ "yJKWiny1LtcamWxkxJvuYLxAJoxEnc9QTV4WHDk5D2N2rKsvuJjcobwgo1Mu1yRuPm5BZeYEW1nKaDSkZi7xSo5" ], \
          "version": 2, "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj", "assetId": null, "feeAssetId": null, \
          "amount": 100000, "attachment": "" }' 'https://example.org/transactions/broadcast'
          

          And we got:

          State check failed. Reason: TransactionNotAllowedByScript

          # Example of transferring Waves with a successful request

          Now, let's try to make a valid transactions with all required proofs. For example, we want to sign this transfer request:

          {
            "type": 4,
            "version": 2,
            "amount": 100000,
            "fee": 500000,
            "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
            "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj"
          }
          
          1. Alice signs this request by her private key through POST /transactions/sign/{signerAddress}

            • Alice address: 3MxjWXEUcVCeiaEUqNcorB5HxSpLsgJCGxE

            • JSON:

            {
              "type": 4,
              "version": 2,
              "amount": 100000,
              "fee": 500000,
              "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
              "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj"
            }
            

            She gets:

            {
              "type": 4,
              "id": "3Pin3DBWL9oW353sGzjdiuvdNp3xKwf2N6B69U5Bv6FS",
              "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
              "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
              "fee": 500000,
              "timestamp": 1525798423735,
              "proofs": [
                "idjwEn3KZWD4R8mKMbonfu6NMuZnyergXXG4T4d5rUQmJu3gs6ChKwAvSXgxai9G7ASZKAm7CExFCt8z59Bv8WB"
              ],
              "version": 2,
              "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj",
              "assetId": null,
              "feeAssetId": null,
              "amount": 100000,
              "attachment": ""
            }
            
          2. Alice gives received JSON of her transaction to Bob

          3. Bob signs it by his private key by same method POST /transactions/sign/{signerAddress}

            • Signer address: 3MqGVvfgqdqqU6P9mTAsLSxyRoRjrHF18Mf

            • JSON:

            {
              "type": 4,
              "id": "3Pin3DBWL9oW353sGzjdiuvdNp3xKwf2N6B69U5Bv6FS",
              "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
              "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
              "fee": 500000,
              "timestamp": 1525798423735,
              "proofs": [
                "idjwEn3KZWD4R8mKMbonfu6NMuZnyergXXG4T4d5rUQmJu3gs6ChKwAvSXgxai9G7ASZKAm7CExFCt8z59Bv8WB"
              ],
              "version": 2,
              "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj",
              "assetId": null,
              "feeAssetId": null,
              "amount": 100000,
              "attachment": ""
            }
            

            He gets:

            {
              "type": 4,
              "id": "3Pin3DBWL9oW353sGzjdiuvdNp3xKwf2N6B69U5Bv6FS",
              "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
              "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
              "fee": 500000,
              "timestamp": 1525798423734,
              "proofs": [
                "J1VEeSFpNE5sE9Gf3GiZ5NarqUWtd5SUAH3HGGmnFVsHntbKsyQxubHS3itaPguYXoEcwFMdtMuLTuZYbmrjifG"
              ],
              "version": 2,
              "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj",
              "assetId": null,
              "feeAssetId": null,
              "amount": 100000,
              "attachment": ""
            }
            
          4. Bob merges proofs in such a way that Alice's proof must be the first, and his proof - the second:

            {
             "type": 4,
             "id": "3Pin3DBWL9oW353sGzjdiuvdNp3xKwf2N6B69U5Bv6FS",
             "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
             "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
             "fee": 500000,
             "timestamp": 1525798423735,
             "proofs": [
               "idjwEn3KZWD4R8mKMbonfu6NMuZnyergXXG4T4d5rUQmJu3gs6ChKwAvSXgxai9G7ASZKAm7CExFCt8z59Bv8WB",
               "J1VEeSFpNE5sE9Gf3GiZ5NarqUWtd5SUAH3HGGmnFVsHntbKsyQxubHS3itaPguYXoEcwFMdtMuLTuZYbmrjifG"
             ],
             "version": 2,
             "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj",
             "assetId": null,
             "feeAssetId": null,
             "amount": 100000,
             "attachment": ""
            }
            
          5. Bob broadcasts the transaction

             {
               "type": 4,
               "id": "3Pin3DBWL9oW353sGzjdiuvdNp3xKwf2N6B69U5Bv6FS",
               "sender": "3N7H4jTBMKtZfNCY86K2ND1rWcvFsGjDT3X",
               "senderPublicKey": "66xdGznqt2AVLMZRHme9vFPC6cvN4yV95wRWPfTus3Qe",
               "fee": 500000,
               "timestamp": 1525798423735,
               "proofs": [
                 "idjwEn3KZWD4R8mKMbonfu6NMuZnyergXXG4T4d5rUQmJu3gs6ChKwAvSXgxai9G7ASZKAm7CExFCt8z59Bv8WB",
                 "J1VEeSFpNE5sE9Gf3GiZ5NarqUWtd5SUAH3HGGmnFVsHntbKsyQxubHS3itaPguYXoEcwFMdtMuLTuZYbmrjifG"
               ],
               "version": 2,
               "recipient": "3MqCPnaoTvE81Es4FSR1m7S6yMUnnJPu9bj",
               "assetId": null,
               "feeAssetId": null,
               "amount": 100000,
               "attachment": ""
             }
            
          Creating smart account
          Video tutorials
          Creating smart account
          Video tutorials