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
    
  2. Create a bloc project.

    $ bloc init < app-name >
    
  3. 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.

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

     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=testUser&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: 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.
  • 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.

  • 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 For full documentation on bloc and bloc server view our API documentation

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