Bloc Server API Walkthrough

Installation

Bloc Server is already running if you launched a Strato Single instance from the Azure marketplace.

Alternatively:

  1. Download Bloc from npm

    $ npm install -g blockapps-bloc
    
    Dependencies

    + NodeJS LTS (v6.9.2) and npm LTS (v4.0.1) version. + Git LTS._

    If npm does not work

    + (Windows) Check that npm is added to the System Environment Variables. Run node -v on cmd to check. + (Linux/Mac) Node and npm should be installed globally.

  2. Create a bloc project.
   $ bloc init < app-name >
During Creation
  • apiURL refers to the Strato Instance to be used for the project, should be changed only when a private Strato Instance is available. The default apiURL http://strato-dev4.blockapps.net should be used for all development and testing purposes.
  • There are two available profiles, strato-dev and ethereum. strato-dev should be used during development and testing on a Strato instance that is not mining such as our dev net, http://strato-dev4.blockapps.net. The ethereum profile is used on Strato instances that are mining. Generally, this is once the project is production ready.
  1. Install project dependencies.

    $ cd < app-name > && npm install
    

Usage

To upload and invoke Smart Contracts, one needs to first generate a public address.

CLI

  • Generate a key to sign your transactions.

    $ bloc genkey
    prompt: Enter a high entropy password. You will need this to sign transactions:
    wrote app/users/admin/735fbcd44b3d999640d381bdfb920cf122628be5.json
    

    NB: bloc genkey defaults to a user named admin. To specify additional users, simply supply the user name as an argument: bloc genkey < user-name >.

  • Run Bloc Server.

      $ bloc start
      bloc is listening on http://0.0.0.0:8000
    
      api is pointed to http://strato-dev3.blockapps.net with profile strato-dev
    

    NB: In general, Bloc Server and Bloc CLI expose the same functionality. This allows you to query and create users with REST requests.

    If bloc start doesn't work
    • On the Terminal, type $ ps -ef | grep bloc, copy the process id for bloc and in type kill -9 <pid>. Run bloc start again.
    • Reboot computer and run bloc start again.

REST API

Users.
  • Get all Users.

    To get all users, we use the /users endpoint.

       $ curl "http://localhost:8000/users"
       ** Sample Response **
       [
         "admin"
       ]
    
  • Create a new user. To create a new user we simply post the username and password to the user endpoint. The response is the user's new public address.

       $ curl -d "faucet=1&&password=securePassword"  http://localhost:8000/users/testUser
       ** Sample Response **
         badf39b2f81bf6be824e7314e72701318485587e
    

    NB: We passed the faucet=1 parameter to the /users endpoint. In development mode, this triggers a transaction sending 1000 ether from the faucet to the newly generated address so you can begin uploading and calling contracts right away.

  • Transfer Ether between users. We've now generated two addresses - let's transfer value from admin to testUser.

       $ curl -d "password=securePassword&toAddress=badf39b2f81bf6be824e7314e72701318485587e&value=10" http://localhost:8000/users/admin/111dec89c25cbda1c12d67621ee3c10ddb8196bf/send
       ** SAMPLE RESPONSE **
       {
         "nonce":0,
         "gasPrice":50000000000,
         "gasLimit":21000,
         "value":"10000000000000000000",
         "codeOrData":"",
         "from":"111dec89c25cbda1c12d67621ee3c10ddb8196bf",
         "to":"00000000000000000000000000000000testUser",
         "r":"",
         "s":"",
         "v":"1c",
         "hash":"3327e8862f68bf89efde9bb594cf58af04befa195db5880f8cfe7cb48e15a103"
       }
    

    NB: 'testUser' refers to the address of the user . The "value" in the transaction response from the server is much larger than the 10 we passed as a parameter. This is because the server response with the smallest unit of ETHER which is WEI, 1ETH * (10^-18)

Contracts.

NB: Currently, bloc supports v3.6 for the Solidity compiler, which makes some of the new version of Contracts incompatible with the older version.

  • Deploy a contract.

    We've learned how to send value from one user to another. We can deploy our first smart contract just as easily, but first let's look at the source code.

      contract SimpleStorage {
        uint storedData;
        function set(uint x) { storedData = x; }
        function get() returns (uint retVal) { return storedData; }
      }
    

    Above is a basic contract called SimpleStorage. It is written in Solidity, the most popular high level language that compiles to EVM bytecode. The contract has a global variable called storedData, and a getter and setter for it. We can upload the contract as follows.

      curl --data-urlencode "password=securePassword" --data-urlencode "src=contract SimpleStorage { uint storedData; function set(uint x) { storedData = x; } function get() returns (uint retVal) { return storedData; } }" http://localhost:8000/users/testUser/111dec89c25cbda1c12d67621ee3c10ddb8196bf/contract
      ** SAMPLE RESPONSE **
      45003a173bc74ee7c25c7798e6748a106fac4a72
    

    The response is the address of the newly created contract.

  • Bootstrapping the Contract.

    Since the contract is now deployed, we can view the Bootstrapped rendition of the Contract compiled. adding the html extension View a scaffolded UI that can call the contracts methods with the .html extension.

    http://localhost:8000/contracts/SimpleStorage/45003a173bc74ee7c25c7798e6748a106fac4a72.html
    

The automatically generated HTML Contract page contains all the fields and methods contained by the contract. All contract methods can be invoked directly by using the textfields and buttons on the webpage. For more details, Visit API Documentation

  • Contract Invocation.

    With our contract deployed, let's call the set function and save some data on the blockchain! We'll call the method "set" with the parameter "x" set to "7". These are passed as post parameters

      $ curl -H "Content-Type: application/json" -d '{"password":"securePassword","method":"set","args":{"x":17},"value":0}' http://localhost:8000/users/testUser/111dec89c25cbda1c12d67621ee3c10ddb8196bf/contract/SimpleStorage/45003a173bc74ee7c25c7798e6748a106fac4a72/call
      ** SAMPLE RESPONSE **
      transaction returned: null
    

    The return value is the return value of the Solidity method, which in this case isn't present.

  • Contract State.

    We didn't see the change in contract state reflected in the response above. How can we introspect into contract states? We use the /state route.

      $ curl http://localhost:8000/contracts/SimpleStorage/d7fdd68abdb83bd79e8d5f83ce3340378593f63f/state
      ** SAMPLE RESPONSE **
       {"set":"function (Int) returns ()","get":"function () returns (Int)","storedData":"17"}
    

    The /state route is the workhorse that drives applications - in most cases UIs are just views of the data available at the /state route.

    NB we did not need to invoke the getter function in SimpleStorage to obtain its state. We'll see a use for getter functions in the next section.

  • Multiple Contracts

    Uploading multiple contracts requires an additional parameter indicating which contract is to be uploaded.

    Consider the simple source file:

         contract Consumer {
            InfoFeed feed;
            uint global;
    
            function setFeed(address addr) {
                feed = InfoFeed(addr);
            }
    
            function callFeed() {
                global=feed.info();
            }
         }
    
         contract InfoFeed {
             function info() returns (uint ret) {
                return 42;
              }
         }
    

    We separately upload these contracts by passing the contract to upload as a parameter:

     curl --data-urlencode "contract=Consumer" --data-urlencode "password=securePassword" --data-urlencode "src=contract Consumer { InfoFeed feed; uint global; function setFeed(address addr) { feed = InfoFeed(addr);} function callFeed() { global=feed.info();}} contract InfoFeed { function info() returns (uint ret) {return 42; }}" http://localhost:8000/users/testUser/111dec89c25cbda1c12d67621ee3c10ddb8196bf/contract
    
     ** SAMPLE RESPONSE **
     e8ae999a084358bd3d2c11f70e20ae4104363eef
    

    and

      curl --data-urlencode "contract=InfoFeed" --data-urlencode "password=securePassword" --data-urlencode "src=contract Consumer { InfoFeed feed; uint global;  function setFeed(address addr) { feed = InfoFeed(addr);} function callFeed() { global=feed.info() } } contract InfoFeed { function info() returns (uint ret) { return 42; }" http://localhost:8000/users/testUser/111dec89c25cbda1c12d67621ee3c10ddb8196bf/contract
    
     ** SAMPLE RESPONSE **
     80aa9aa1482f36b1861b8580fa7c2953f6209466
    

    Next, let's register our instance of InfoFeed with Consumer.

     curl -H "Content-Type: application/json" -d '{"password":"securePassword","method":"setFeed","args":{"addr":"80aa9aa1482f36b1861b8580fa7c2953f6209466"},"value":0}' http://localhost:8000/users/testUser/111dec89c25cbda1c12d67621ee3c10ddb8196bf/contract/Consumer/e8ae999a084358bd3d2c11f70e20ae4104363eef/call
    
     transaction returned: null
    

    To confirm the change, check the state route:

     curl http://localhost:8000/contracts/Consumer/e8ae999a084358bd3d2c11f70e20ae4104363eef/state
    
     {
       "setFeed":"function (Address) returns ()",
       "callFeed":"function () returns ()",
       "feed":"80aa9aa1482f36b1861b8580fa7c2953f6209466",
       "global":"0"
      }
    

    Note that feed has been succesfully registered. Finally, let's consume the feed:

     curl -H "Content-Type: application/json" -d '{"password":"securePassword","method":"callFeed","args":{},"value":0}' http://localhost:8000/users/testUser/111dec89c25cbda1c12d67621ee3c10ddb8196bf/contract/Consumer/e8ae999a084358bd3d2c11f70e20ae4104363eef/call
    
     transaction returned: null
    

    Finally, we can check the state update:

     curl http://localhost:8000/contracts/Consumer/e8ae999a084358bd3d2c11f70e20ae4104363eef/state
    
     {
       "setFeed": "function (Address) returns ()",
       "callFeed": "function () returns ()",
       "feed": "80aa9aa1482f36b1861b8580fa7c2953f6209466",
       "global": "42"
     }
    
  • Constructor Arguments Solidity contracts support constructor arguments. Let's modify SimpleStorage to make use of a constructor.

     contract SimpleStorage {
        uint storedData;
        function SimpleStorage (uint constructorInt) { storedData = constructorInt; }
        function set(uint x) { storedData = x; }
        function get() returns (uint retVal) { return storedData; }
      }
    

    Now, to upload SimpleStorage we use

FAQs

1. How to use the apiURL and setup a private strato instance?

The apiURL refers to the strato instance endpoint to be used for a project. For all development and testing purposes Blockapps offers a strato instance to interact with the testnet. The apiURL http://strato-dev4.blockapps.net points to our testnetOnce the project is ready to move to production, contact Blockapps to help setup a pivate or consortium blockchain. To get your own Strato Instance, follow the Quick-Start guide on the Microscoft Azure to get started in minutes. Learn more

2. What is the difference between the two profiles: ethereum and strato-dev ?

ethereum : For a mining blockchain.

strato-dev: For development and testing on the testnet.

3. Why can multiple addresses be created under the same username?

`bloc` has usernames because it acts a private key registry for you Ethereum
accounts. Within the Ethereum blockchain there is no concept of users, only
of accounts, transactions, and blocks. The key registry has the username
to make it easier to sign transactions from an account requiring just a password.

4. bloc stops working abruptly, how to debug?

bloc stops working when the request parameters or the request URL are malformed. Check the bloc console log to find the error in the request send. Also, validate the JSON parameters.

5. What do some of the responce keys actually mean?

`"r"` : Elliptic curve signature value (internal)

`"s"` : Elliptic curve signature value (internal)

`"v"` : Elliptic curve signature recovery value (internal)

`"nonce"` : The number of transactions made by the signing address

`"gasPrice"` : The amount of ether per computational step.

`"gasLimit"` : The max amount of gas that can be used. i.e. (gasPrice * computational-steps) <= gasLimit

6. How to view the Bootstrapped version of a Contract?

bloc automatically created a simple Bootstrapped front-end for the Contract for the users to easily test their methods and arguments. To do so, type http://localhost:8000/contracts/SimpleStorage/45003a173bc74ee7c25c7798e6748a106fac4a72.html in the browser. For more details, Visit API Documentation

7. Why doesn't the Contract Front-End work?

If some of the fields in the request body have been left empty or of invalid data type, bloc would interpret this as a malformed request and crash, while generating a crash report on the console. If the Webpage becomes unresponsive, check your bloc server console to debug. Run bloc start again to restart.

8. What do the terms faucet and extabi mean?

extabi : The Application Binary Interface, ABI, is the interface between two program modules. One module is at the machine code level, the interface is a method for encoding/decoding data in/out of the machine code. In case of Smart Contracts, it is used to store and get data from an uploaded smart contract.

faucet : Takes an argument convertible to Address and supplies it with 1000 ether. This is not available on a live network, for obvious reasons.

9. What version of the Solidity Compiler (solc) does bloc use? Why aren't some of the latest contract examples compiled by bloc?

'bloc` currently uses an older version of the Solidity Compiler, which makes some of the newer contracts incompatible with bloc, try to use the Solidity Web Compiler to check if the contract works and compiles without any errors. To verify the smart contract code one can use the Strato solc compiler available at Strato Documentation

For full documentation on bloc and bloc server view our API documentation

For full documentation on bloc and bloc server view our API documentation