NAV
javascript shell

Introduction

Blockchain-based applications need to pull information from the blockchain. BlockApps makes that process simple with an intuitive RESTful API for querying the Ethereum Blockchain.

dApps

What is a dApp?

A dApp is a decentralized App.

dApps on Ethereum can be entirely decentralized, meaning that they can run entirely peer-to-peer, like BitTorrent.

Entirely P2P dApps require downloading a stack of desktop software tools so your computer can be an Ethereum node that talks to the Ethereum network.

BlockApps helps you develop webapps more quickly by being that stack for you. Just use the BlockApps API to build and prototype webapps that interact with the Ethereum Blockhain in any web browser.

How are dApps created?

A basic dApp consists of a frontend user interface in a web browser and a smart contract on the blockchain. They can be comprised of an unlimited number of parts and features on top of this. dApps can also call other dApps.

What are the basic components of dApps on Ethereum?

Check out our introductory tutorial for a quick overview of basic dApp concepts.

BlockApps

How does BlockApps work?

Our Haskell-based Ethereum network peer (client) is compliant with the PoC9 Ethereum testnet and can also be used as a web server. But you don’t have to install the peer, just use the API.

We have static GET routes for transactions, blocks and account states. More generally, we support query strings.

Is there a demo or tutorial?

Yes! Visit the links at left for a demo and tutorial of how to parse and visualize blockchain records requested using the BlockApps API.

Coming Soon:

Sample Queries

Check out some sample queries made using the BlockApps API…

Resources are located via GET routes. Requests are routed by the return type - blocks, accounts or transactions.

We have a few pre-built simple routes shown below, and the API supports a general querystring syntax. Routes are meant to be invoked via HTTP requests and return raw JSON.

By Block

Blocks are fetchable by a variety of queries

By Account

Accounts, too, are easily queried.

By Address

See the transations to and from addresses:

By Transaction

Get information about pushed transactions

Endpoints

There are multiple RESTful endpoints, corrensponding to:

All requests are to http://stablenet.blockapps.net

GET Block

$.get( "http://stablenet.blockapps.net/query/block") {number: 42})
  .done(function( data ) {
    //operations on the returned json block
  });
curl "http://stablenet.blockapps.net/query/block?number=42"

The command at right returns JSON structured like this:

[
  {
    "next":"/query/block?index=43&number=42",
    "kind":"Block",
    "blockUncles":[],
    "receiptTransactions":
      [
        {
          "transactionType":"FunctionCall",
          "gasLimit":30000,
          "kind":"Transaction",
          "data":"00",
          "gasPrice":10000000000000,
          "to":
          {
            "address":"fd888462ba01400a37768e53791df4617c77cd08"
          },
          "value":16,
          "r":"244fd84898d7c25537dc9a19b03f7ebf2796de804eb886e40a5ba2b4ff994788",
          "s":"46ed2a17765fb10f46f9a70c2e5a8e3635113e03b5785b32b0f77c942e7188d1",
          "v":"1c",
          "nonce":0
        }
      ],
      "blockData":
        {
          "extraData":0,
          "gasUsed":0,
          "gasLimit":3141592,
          "kind":"BlockData",
          "unclesHash":"1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
          "mixHash":"0000000000000000000000000000000000000000000000000000000000000000",
          "receiptsRoot":"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
          "number":42,
          "difficulty":132480,
          "timestamp":"2015-06-24T17:41:27.442848000000Z",
          "coinbase":"5b42bd01ff7b368cd80a477cb1cf0d407e2b1cbe",
          "parentHash":"6297f5531e118e73a204d5e2a1e1abef6650f3463375b9ce5439869b5271e95d",
          "nonce":18446744073709551615,
          "stateRoot":"9eb06ef32021054a4043cb65381910414d572e3ea5a1751036987cdc44c8e943",
          "transactionsRoot":"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
        }
  }
]

GET /query/block?

Note that blocks come with a next field that contains the index for the next 100 results.

Parameter Description
number Returns blocks that match a specific number
maxnumber Returns blocks with a number less than a maximum
minnumber Returns blocks with a number greater than a minimum
gaslim Returns blocks that match the specified gas limit
maxgaslim Returns blocks with agas limit less than a maximum gas limit
mingaslim Returns blocks with a gas limit greater than a minimum
gasused Returns blocks that match the specified gas used
maxgasused Returns blocks with gas used less than a maximum
mingasused Returns blocks with gas used greater than a minimum
diff Returns blocks with a specific difficulty
maxdiff Returns blocks with a difficulty less than a maximum
mindiff Returns blocks with a difficulty greater than a minimum
txaddress Queries blocks by their contained transaction addresses
coinbase Queries blocks by the coinbase of contained transactions
address Queres blocks by the address of contained transactions
hash Queries blocks by their hash

GET Account

$.get( "http://stablenet.blockapps.net/query/account"), {address: "af8b2d3fe28201476fc0a3961f8f9690693f3ef4"})
  .done(function( data ) {
    //operations on the returned json block
  });
curl "http://stablenet.blockapps.net/query/account?address=af8b2d3fe28201476fc0a3961f8f9690693f3ef4"

The above command returns JSON structured like this:

[
  {
    "contractRoot":"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "kind":"AddressStateRef",
    "balance":"1809251394333065553493296640760748560207343510400633812824226722060731360952",
    "address":"af8b2d3fe28201476fc0a3961f8f9690693f3ef4",
    "code":"",
    "nonce":864
  }
]

GET /query/account?

Parameter Description
balance Returns accounts that match a specific balance
maxbalance Returns accounts with a balance less than a maximum
minbalance Returns accounts with a balance greater than a minimum
nonce Returns accounts that match a specific nonce
maxnonce Returns accounts with a nonce less than a maximum
minnonce Returns accounts with a nonce greater than a minimum
address Returns accounts with the specified address

GET Transaction

$.get( "http://stablenet.blockapps.net/query/transaction"),{value:0})
  .done(function( data ) {
    //operations on the returned json block
  });
curl "http://stablenet.blockapps.net/query/transaction?value=0"

The above command returns JSON structured like this:

[
  {
    "transactionType":"FunctionCall",
    "next":"/query/transaction?index=39780",
    "hash":"831716403cf9919e96ef122234b632e3be34c69c475d4f576b86a14b4b47eddc",
    "gasLimit":90000,
    "codeOrData":"de5f72fd",
    "gasPrice":10000000000000,
    "to":"b8cd5067227fdec355c5531accbcdf734a0869e8",
    "value":"0",
    "from":"1c11aa45c792e202e9ffdc2f12f99d0d209bef70",
    "blockNumber":32308,
    "r":"6acd4884c360d5906fc1434313c4325e6a1ff90a8dccffdc2879abab03385431",
    "s":"2ba4e89ebc46a0800ef71876f6501f34caf8d098b57cbb73c64739e04894aaf4",
    "v":"1b",
    "nonce":0
  }
]

GET /query/transaction?

Parameter Description
from Returns transactions from the specified address
to Returns transactions to the specified address
address Returns transactions involving the specified address
value Returns transactions of a specific value
maxvalue Returns transactions with a value less than a maximum
minvalue Returns transactions with a value greater than a minimum
gasprice Returns transactions with the specified gas price
maxgasprice Returns transactions with a gas price less than a maximum
mingasprice Returns transactions with a gas price greater than a minimum
gaslimit Returns transactions with the specified gas limit
maxgaslimit Returns transactions with a gas limit less than a maximum
mingaslimit Returns transactions with a gas limit greater than a minimum
blocknumber Returns Transactions with a blocknumber
$.get( "http://stablenet.blockapps.net/transactionResult/4ee3298d059e3664673880db272aebd5215f23554265e3e1e9de6dbf02f9f9c2"))
  .done(function( data ) {
    //operations on the returned json block
  });
curl "http://stablenet.blockapps.net/transactionResult/4ee3298d059e3664673880db272aebd5215f23554265e3e1e9de6dbf02f9f9c2"

The above command returns JSON structured like this:

[
  {
    "contractRoot":"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "kind":"AddressStateRef",
    "balance":"1809251394333065553493296640760748560207343510400633812824226722060731360952",
    "address":"af8b2d3fe28201476fc0a3961f8f9690693f3ef4",
    "code":"",
    "nonce":864
  }
]

GET /transactionResult/#hash

This route returns information about the the transaction passed to it as #hash

Types of transactions

Transaction Format
Contract If toAddress != Null and len(code)>=0 then we have a Contract.
FunctionCall If toAddress == Null and len(code)>0 then we have a FunctionCall.
Transfer If toAddress != Null and len(code)==0 we have a Transfer.

Extra parameters

Parameter Description
raw passes the pre-processor and gives you the raw result (default: raw=0).
index a cursor for querying the next 100 items correctly. Also see page.
page append page=n to page any query with many results (default: page=0).*

Paging

Paging begins at 0 so /query?block=xxxx is equivalent to /query?block=xxxx&page=0.

Indexing

For blocks we support indexing. If you want to query a large range, supply index=n where n-1 is the last block that you queried. This will supersede paging once we include indexing for accounts.

Demo

We have a demo application using the BlockApps API to create a block and address explorer. Try the demo below then follow the tutorial to see how it’s built.

To learn how to build the demo, continue to the next section.

Tutorial

Building Your Own Address Explorer

Building an Address Explorer on top of BlockApps is easy. In fact, BlockApps does most of the work for you, providing all the information you need to query and display information about an account.

Background

In order to build an address explorer, you must first know a bit about Ethereum. If you’re completely new to Ethereum and we suggest you check out ethereum101.org.

Let’s start with a basic understanding of blocks, blockchains, Ethereum, accounts, addresses, transactions, contracts, and gas.

Getting Started

Let’s first get our basic code set up. (You can find the full code for this tutorial here.)

The following is a slimmed down version of what’s available in the repository. The version we’ll create here won’t contain an input box to enter your Ethereum address (we’ll leave that as an experiment for the reader), and instead your Ethereum address will be pulled from the browser’s query string. There are also many features that have been left out, but the good news is you’ll see just how easy is it to get the bulk of an address explorer up and running.

/* address-explorer.js */

$(document).on("ready", function() {
  console.log("Address Explorer JS up and running.");
});

address-explorer.js

(code at right)

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>My Address Explorer</title>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet">
  <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
  <script type="text/javascript" src="./address-explorer.js"></script>
</head>
<body>
  <div class="container">
    <h1 class="twelve columns">
      Your Account
    </h1>
    <div class="five columns">
      <span id="displayed_balance" class="value">&nbsp;</span>
      <br><span class="label">Total Balance</span>
    </div>
    <div class="four columns">
      <span id="transaction_count" class="value">&nbsp;</span>
      <br><span class="label">Transactions</span>
    </div>
    <div class="two columns">
      <span id="blocks_mined_count" class="value">&nbsp;</span>
      <br><span class="label">Blocks Mined</span>
    </div>
    <h4 class="twelve columns">Activity</h4>
  </div>
</body>
</html>

index.html

(code at right)

After saving the above two files, you should be able to open index.html in your browser. You should see a very basic HTML structure with no data, an if you open up your developer console you should see “Address Explorer JS up and running.” printed there.

This means were good to move onto the next step!

Getting the Address

For the purposes of this tutorial, we’re not going to build a fancy interface that asks for the users address, mostly because it distracts from simplicity of the tutorial. Instead, we’re going to get the address from the query string. To make it even easier, we’re going to assume the whole query string is the address. Pulling the query string is easy, so you should be able to edit address-explorer.js to look like this:

address-explorer.js

/* address-explorer.js */

$(document).on("ready", function() {
  console.log("Address Explorer JS up and running.");
  var address = window.location.search.substring(1);
  console.log("Address: " + address);
});

Now, if we navigate to /index.html?6a56cf7a57405800b18e3e0940628c190cfa73bc, we should see the address 6a56cf7a57405800b18e3e0940628c190cfa73bc printed in the console logs.

Once we have the address, we can begin requesting data from BlockApps.

Getting the Account Balance

Perhaps the most important piece of information to request is the account balance. BlockApps provides an API endpoint that will give you the balance of an address over time, where the most recent entry is the current account balance. Here’s an example using address on the network as of this writing:

http://api.blockapps.net/query/account/address/6a56cf7a57405800b18e3e0940628c190cfa73bc

Note: Ethereum is churning through multiple test networks at the time of this writing, so the address listed above might not exist at the time you read this. Make sure to use as address you know exists!

You can see that that endpoint provides multiple objects in an array. We’ll use jQuery to make the request and parse the result, and then add the balance onto the page:

address-explorer.js

/* address-explorer.js */

$(document).on("ready", function() {
  console.log("Address Explorer JS up and running.");
  var address = window.location.search.substring(1);
  console.log("Address: " + address);

  $.getJSON("http://api.blockapps.net/query/account/address/" + address, function(balances, textStatus, jqXHR) {
    $("#displayed_balance").html(balances[0].balance);
  });
});

Note: We’re not checking for errors here. This is to make the tutorial easy, but for your own application you should handle the case where the request fails.

You should now see something like this!

From here, we can now move onto getting a list of this accounts transactions.

Getting Account Transactions

For an account explorer to be useful, we want to see all the transactions that were made from this account as well as all transactions sent to this account. Fortunately, BlockApps helps us with this significantly by providing an endpoint that does exactly that.

Here’s an example for the same account used above:

http://api.blockapps.net/query/transaction/address/6a56cf7a57405800b18e3e0940628c190cfa73bc

Like requesting an account balance, BlockApps provides us with an array of objects as a response. Each of these objects represent a transaction that involved the address requested, and as mentioned, transactions can be of many types. BlockApps makes it easy for you to distinguish between the types of transactions by adding a transactionType key to each transaction. The values are as follows:

Notice that for all of the transactions, none of them contain a timestamp. This is because that information is stored on the block, and so regardless of type, we’ll need to request the block so we can display that as well.

Before adding the above request into our address explorer, lets first cover getting the blocks associated with each transaction.

Getting a Transaction’s Block

Each transaction object shown above has an associated block id (the blockId key). We’ll use this id to request the associated block.

Here’s an example:

http://api.blockapps.net/query/block/blockid/225955

Notice that with this request, we’re given an array containing a single object. This object has multiple useful pieces of information, but we’ll only cover what’s important to us right now. Here’s what we’ll need:

From here we can take both the transaction request and the block requests and put them into our app:

/* address-explorer.js */

$(document).on("ready", function() {
  console.log("Address Explorer JS up and running.");
  var address = window.location.search.substring(1);
  console.log("Address: " + address);

  // Get the account balance.
  $.getJSON("http://api.blockapps.net/query/account/address/" + address, function(balances, textStatus, jqXHR) {
    $("#displayed_balance").html(balances[0].balance);
  });

  // Function for getting individual blocks.
  var createTransactionHandler = function(transaction) {
    return function(result, textStatus, jqXHR) {
      block = result[0];
      console.log(transaction, block.number);
    };
  };

  // Get each transaction, and get each block associated with the transaction.
  $.getJSON("http://api.blockapps.net/query/transaction/address/" + address, function(transactions, textStatus, jqXHR) {
      $("#transaction_count").text(transactions.length);

      for (var i = 0; i < transactions.length; i++) {
        var transaction = transactions[i];
        $.getJSON("http://api.blockapps.net/query/block/blockid/" + transaction.blockId, createTransactionHandler(transaction));
      }
  });
});

address-explorer.js

You’ll notice that the last block of code at right requests the transactions, and then we request each transaction’s block within a for loop. Because we’re in that loop, we have to create a new handler for each block or else we’ll have issues with Javascript closures. This makes createTransactionHandler the primary method where we handle transactions and their blocks. You’ll notice that currently, it’s just outputting transactions and their block number to the console.

Displaying Transactions

As mentioned, perhaps the hardest part about creating an address explorer is simply displaying all the information. What we’ll want to do is display the transactions with any associated information based on the transaction type (for instance, for a Transfer, we’ll want to display who it’s from and who its to). We’ll also want to make sure these transactions are ordered by date, newest first, as that’s important to the user. I’ve provided the associated code below. Note that this is simply one way to output this information, and for the purposes of this tutorial I’ve kept it very simple.

address-explorer.js

/* address-explorer.js */

$(document).on("ready", function() {
  console.log("Address Explorer JS up and running.");
  var address = window.location.search.substring(1);
  console.log("Address: " + address);

  // Get the account balance.
  $.getJSON("http://api.blockapps.net/query/account/address/" + address, function(balances, textStatus, jqXHR) {
    $("#displayed_balance").html(balances[0].balance);
  });

  var addActivity = function(timestamp, message) {
    var date = new Date(timestamp);
    var element = $(document.createElement("div"));
    element.addClass("transaction twelve columns");
    element.html(date.toISOString() + " &mdash;  " + message);
    element.data("date", date.getTime());

    // Keep DOM elements ordered by date.
    var elements = $(".transaction").detach().get();
    elements.push(element);
    elements = elements.sort(function(a,b) {
      a = parseInt($(a).data("date"));
      b = parseInt($(b).data("date"));
      return b - a;
    });
    $(".container").append(elements);
  };

  // Function for getting individual blocks.
  var createTransactionHandler = function(transaction) {
    return function (result, textStatus, jqXHR) {
      block = result[0];

      switch (transaction.transactionType) {
        case "Contract":
          addActivity(block.timestamp, "New contract added to the network at cost of " + block.gasUsed + " wei.");
          break;
        case "FunctionCall":
          addActivity("Function call to contract at cost of " + block.gasUsed + " wei.");
          break;
        case "Transfer":
          if (transaction.to == address) {
            addActivity(block.timestamp, "Credit of " + transaction.value + " wei sent from " + transaction.from + ".");
          } else {
            addActivity(block.timestamp, "Debit of " + transaction.value + " wei sent to " + transaction.to + ".");
          }
          break;
        default:
          return;
      }
    };
  };

  // Get each transaction, and get each block associated with the transaction.
  $.getJSON("http://api.blockapps.net/query/transaction/address/" + address, function(transactions, textStatus, jqXHR) {
      $("#transaction_count").text(transactions.length);

      for (var i = 0; i < transactions.length; i++) {
        var transaction = transactions[i];
        $.getJSON("http://api.blockapps.net/query/block/blockid/" + transaction.blockId, createTransactionHandler(transaction));
      }
  });
});

You should now have something that looks like this:

From here, we can now perform our last step of the process, which is getting the amount of blocks mined by an address.

Getting Blocks Mined by an Address

So far, we’ve shown everything related to an address that affects balance, but we’re missing one thing. We still haven’t shown blocks mined directly by the address, which is the last piece needed to show all the activity that’s happened on an address. Mining will increase the amount of either in your account, so it’s especially important for an address explorer.

Luckily, BlockApps makes this easy. Requesting blocks mined by an address is as easy as requesting an address’s transactions. Here’s an example:

http://api.blockapps.net/query/block/coinbase/6a56cf7a57405800b18e3e0940628c190cfa73bc

You’ll notice that the output of this request differs slightly from the output when we request blocks by id. This will likely change in the future, however, the request still returns an array of blocks, and the relevant data we’re interested can be found in the blockData key.

Now that we have each block mined by this address, we can go ahead and add it to our activity list. To do this, you’ll just need to add this block of code at the bottom of address-explorer.js’s main function:

// Get blocks mined by the address.
$.getJSON("http://api.blockapps.net/query/block/coinbase/" + address, function(blocks, textStatus, jqXHR) {
    $("#blocks_mined_count").html(blocks.length)

    for (var i = 0; i < blocks.length; i++) {
      var block = blocks[i];
      addActivity(block.blockData.timestamp, "Mined block #" + block.blockData.number + " with a block reward of 1500000000000000000 wei.");
    }
});

And that’s it! Mined blocks are now included in the list as activities like transactions; they’re also sorted, and the number of blocks mined is displayed up top as well. You should now have an explorer that includes minded blocks, like this!

Wrapping Up and Further Study

From this tutorial, you should have learned how to request enough information from BlockApps to create your own address explorer. The explorer you created was basic, and there are a few things you can do to make your explorer more usable and fully featured:

There’s a lot you can do, and this is just of taste of what BlockApps can do to help you build apps on Ethereum. I hope you enjoyed it, and don’t hesitate to ask us any questions. Thanks!

Source Code

You can find the full code for this tutorial here.

Further Resources

Want to learn more about dApps?

Check out dApps for Beginners which will teach you how to use Ethereum using a full stack.

Also sign up for our newsletter to hear more about future BlockApps tutorials.