@gliechtenstein

The Future of Native Mobile Apps on Blockchain — What They Should Look Like, and How to Build One…

There are a lot of good reasons to have a standalone native mobile app for your ethereum token/smart contract/DApp (Decentralized App):

  • Accessibility: Just a single tap away from the home screen means more frequent usage
  • Independence: You can provide custom user experience just for your users who sign in with the app specific private key. You control your own user experience and don’t have to depend on generic web browsers or generic wallet UI.
  • Optimized UX: Relying on generic wallets or generic DApp browsers means you delegate all the transaction-related UX to the browser. This means you can’t provide an optimized, dead simple user interface specific to your DApp. With your own dedicated app, you can build a streamlined interface with no confusing parts.
  • Mobile specific features: You can make use of features like push notifications, bluetooth, camera, etc. which can significantly improve user experience.

But as you start thinking about building mobile apps, you will find yourself immediately confronted with some critical challenges:

  1. Risk: You probably have too much on your plate already with your protocol/smart contract/token and don’t have the time or resources to build an app, not to mention maintaining it. And having a dedicated mobile code base that only a few people can understand and maintain is a risk and a liability when your main business should be in the protocol.
  2. You really shouldn’t be the one building the app: You probably want to build something that will last forever, even after your current team moves on. The goal is for the community to build clients on top of your protocol instead of you being the sole developer of a single gateway. Pushing a single dominant implementation from the “official team” only discourages participation from 3rd party developers and doesn’t help with decentralization.
  3. Fabric vs. Single App: You don’t want to build a single app, you want your protocol to be a fabric of the decentralized Internet. Ideally it should be used by all kinds of different apps, not just a single monolithic one that you developed by yourself.

These are real problems with no clear answers, with few people willing to talk about them. It occurred to me that one solution may be to rethink what an “app” is. To that end I tried to create a dead simple framework to bring us closer to that realization.

I started by building a simple ERC20 token mobile app that looks like this:

Throughout the rest of this article, I will discuss:

  1. Ingredients: Walk through all the technologies used in this project, from backend to frontend.
  2. Implementation: High level overview of how I built the mobile app
  3. Lessons: what I learned from building an app this way and what I think mobile apps on blockchain will look like in the future.

While I use specific tools and frameworks throughout this post, the general principle and the lesson should be applicable for anyone who’s thinking about building mobile apps on Ethereum.

Ingredients

Before getting to the mobile app, let’s take a look at all the ingredients we need to build the full stack:

  • Backend: Smart contract
  • Frontend: Web + Mobile
Solidity Smart Contract

Since this post is not a tutorial about how to write smart contracts, I will just share a simple ERC20 token contract I deployed to Rinkeby (an Ethereum testnet).

You can find it in production here (remember to connect to Rinkeby): https://gliechtenstein.github.io/erc20/web/

And the source is here: https://github.com/gliechtenstein/erc20/tree/master/contracts

The code itself is 99% copy and pasted from OpenZeppelin contracts for simplicity and 1% customized.

The cool thing about standards like ERC for Ethereum is you can write once and use it everywhere, so most developers don’t have to worry about coming up with their own secure implementation, they can just reuse most of it and customize only what they need to. The entire community shares the benefits.

This is very in line with what I am trying to achieve with the solution I’m about to discuss in this article. The difference is Zeppelin and friends are focused on the backend (smart contract) and I am focused on the frontend (mobile app).

Web3.js DApp

I wrote a simple web3.js Dapp for dealing with the ERC20 token I deployed in the previous section.

For simplicity, I didn’t use complex tools and frameworks like Truffle, et al. It’s literally just a single flat HTML file. You can check out the code here: https://github.com/gliechtenstein/erc20/blob/master/web/index.html

INFURA : A Trusted Node, trusted by many, including MetaMask.

Most DApp developers nowadays acknowledge that it’s unrealistic to expect all users to download the entire blockchain which is hundreds of gigabytes. In fact, most users use a 3rd party trusted node instead. This is where the MetaMask desktop browser extension comes in.

MetaMask takes a “thin client” approach. Instead of downloading the full blockchain, it connects to a trusted node called Infura. Because of the public key cryptography that powers the whole blockchain — you sign each transaction with your local private key before broadcasting to the network so the network can’t forge it — it is generally considered safe enough to use trusted nodes just for broadcasting.

For mobile development, it makes even more sense to use trusted nodes like Infura because nobody wants to download tens of gigabytes of blockchain, waste network traffic and kill their battery from constant peer to peer synchronization. So let’s use Infura.

Jasonette: Cross-platform Native Mobile App Framework

The first building block is the native UI. We’ll use Jasonette, a markup driven approach to building cross-platform native apps.

Jasonette is like a web browser but for building native apps. Just like how web browsers interpret HTML on the fly and render it on the browser screen, Jasonette interprets a JSON markup to construct a native app on the fly on iOS and Android.

The markup syntax supports expression of everything from Model to View to Controller, so just a single JSON markup is all you need to build a native app.

Quick intro to how Jasonette works:

In-depth tutorial:

Agent: Microservice on the Mobile Frontend

One important built-in feature for Jasonette that’s critical for our use case is agent.

An agent is like a microservice that you can embed in your native app frontend. It automatically forms a two way communication channel between the parent native app and itself, allowing them to communicate via a JSON-RPC protocol.

For example, you can take any web app that works in a browser, embed it in a native app as an agent, and instead of rendering some API data into the DOM, send it to the parent app as an event. Then the app can render it natively.

We will use agent to embed our existing web3 DApp into a native app and use it as a data source (and use the native part to render the data).

Take a quick look at the following page to learn more about agents:

Implementation

Now we’re ready to build the mobile app.

The above diagram is a quick overview of the overall data flow.

  • The user interacts with the native UI.
  • The native UI makes a request to the “DApp container” (which contains your web3 DApp agent)
  • The DApp container makes a request to the “Wallet container” agent (for now, just think of it as a mobile equivalent of MetaMask)
  • The wallet container then connects to Ethereum.

All of these are inter-connected through the JSON-RPC protocol, and the application — all three modules — is entirely described in JSON markup.

Before we jump in, just a reminder that you can find the entire source code at:

With that said, now let’s take a look at each module.

1. Native UI

The first building block is the native UI. Jasonette has a built-in templating engine — also written in JSON — that can take any JSON object and render into a native layout and UI components, as well as express native API function calls in JSON markup.

In this case we‘ll use the DApp container — which we’ll discuss in the next section — as data source, so we define the template and wait for a response from the DApp container. Once the DApp container triggers an event we’ll render the data against our template. Here’s the full markup:

https://github.com/gliechtenstein/erc20/blob/master/mobile/app/main.json

The cool thing about the markup driven approach is that the application logic is completely separated from the device. This means you can store and serve the app from anywhere (like how web browsers do it). It could be stored in a remote server, locally on the device, or even on decentralized storage like IPFS.

Let’s step back and think about what this means. By separating application from the device, we can make sure that regardless of whatever happens to Apple or Google in the future, our app will be portable to a new platform as long as the framework itself is ported to that new dominant platform. And this is why Jasonette chose JSON as the markup language, JSON is the most popular format for machines to store and communicate data with one another, therefore it is likely that the hypothetical “new platform” of the future will also support JSON as first class citizen.

For our MVP app, we serve it from a remote JSON hosted on github.

2. DApp Container

The second building block is the DApp container.

There are a couple of things to note from this diagram:

  1. The user ONLY interacts with the native UI. To the user the DApp is invisible and it simply functions as a data source.
  2. The native module forwards the user request to the DApp container through JSON-RPC.
  3. The DApp container then makes a request to Ethereum network (thanks, Infura) and when it gets a response back, forwards it back to the parent native app, which is rendered with the native template mentioned above.

We instantiate the DApp container as an agent. Declaring an agent involves simply adding 3 lines of JSON to the existing app markup:

{
"$jason": {
"head": {
"title": "Web3 DApp in a mobile app",
"agents": {
"eth": {
"url": "
https://gliechtenstein.github.io/erc20/web"
}
},
...
}
}
}

In this case we initialize the DApp container and name it eth, which we will use as the ID when we make JSON-RPC calls.

Here’s the full source: https://github.com/gliechtenstein/erc20/blob/master/mobile/app/main.json

Note that we have not touched the original web app. We simply embedded our DAPP as an agent and are using it as an instant pseudo-backend for the mobile app. To be clear, you don’t have to do this and just keep a separate agent just for embedding into the mobile app, but I just wanted to show how you can reuse the same DApp for mobile.

3. Wallet Container

Writing to Ethereum is trickier than reading. We must be more careful because it deals with creating actual transactions and sending real money.

Normally when building a regular DApp, we use the web3.js library to make an API call like this:

contract.transfer.sendTransaction(receiver, tokens, {
to: contract.address,
gasLimit: 21000,
gasPrice: 20000000000
}, function(err, result) {
// Render the DOM with result
})

This method sendTransaction actually does two things:

  1. Create an encoded transaction object for a contract method called "transfer".
  2. Sign and broadcast the transaction object to Ethereum via JSON-RPC.

For our project instead of having the DApp handle both, we will:

  1. Let our DApp container handle only the first part
  2. and create a separate container called “Wallet container” to handle the second part

By separating the two, the DApp container doesn’t have to deal with private keys, but delegates it to the wallet container just like how MetaMask deals with this issue automatically on desktop. That way the DApp developer can focus on the application logic.

So instead of using the sendTransaction method, we first use an API called getData to get a transaction object:

var tx = contract.transfer.getData(receiver, tokens)

And then pass that back to the parent app through the $agent.response API:

$agent.response({ tx: tx })

The parent native app then will pass it along to our new wallet view.

The wallet view (and the wallet agent it contains) will take this unsigned transaction data, sign it, and then broadcast it through Infura. You can check out the wallet view source code here: https://github.com/gliechtenstein/erc20/blob/master/mobile/wallet/wallet.json

Here’s the wallet agent code: https://github.com/gliechtenstein/erc20/blob/master/mobile/wallet/wallet.html

Note that the “wallet view” is a completely separate sandboxed view of its own, just like how MetaMask opens up in a new popup browser. This is by design. This insulates the DApp developer from ever having to deal with private keys.

Why build this way?

To recap, here’s how our entire mobile app works:

  • The user ONLY interacts with the UI, which is native
  • The native UI is constructed from a markup in realtime, instead of a hardcoded compiled program.
  • The native UI embeds multiple microservice-like web containers running isolated HTML/JavaScript apps, communicating with one another through JSON-RPC.
  • The only “program” the developer needs to write is the JSON markup that describes the UI and the instructions.

What’s the benefit of building an app this way, especially for a decentralized network like Ethereum?

1. Easy

It’s simply much easier to build the app this way. You don’t have to rewrite your DApp to work on mobile, you don’t need to hire a mobile developer, you don’t need to maintain a separate mobile code base.

All you need to do is:

  1. Write a couple of markup files representing each view
  2. Embed your own DApp as an agent like an iframe
  3. Let your DApp and the parent native app communicate through a protocol such as JSON-RPC.

This gives you a single codebase that works both as your website and for mobile. The only thing you need to maintain is the markup. But even the markup — since it’s public — can be shared by different apps.

We can look at how the ERC standards for Ethereum work in order to understand the implication of this. Most ERC20 token developers simply inherit from Zeppelin’s zeppelin/solidity — the most audited and therefore most secure ERC20 token contract — and implement their own customization on top, which makes it much easier to build smart contracts while keeping it safe.

And I predict that same type of standards may emerge for building secure mobile frontends.

2. Everlasting

Every view is expressed as a single standalone JSON markup — just like all web pages are expressed as a single HTML markup — nothing hides behind complex dependencies that can make a piece of code hard to understand. None of the JSON markup syntax is device specific. Every view is standalone and sandboxed which also contributes to simplicity. Simplicity begets transparency.

To build a protocol that will last forever, you want your clients to be as transparent as possible, so a free market can form around clients for your protocol. This way your protocol can live on forever even after you move on from the project.

3. Customizable

The example below uses exactly the same DApp we used above, but just with a different view markup to create a completely different interface.

I didn’t have to do anything fancy to make this change. What you see above is literally a single JSON markup which I forked from the earlier version. It took me less than 5 minutes to write:

https://github.com/gliechtenstein/erc20/blob/master/mobile/app/simple.json

What’s really cool about this is that YOU TOO can take the same markup and customize it for your own ERC20 token because all ERC20 tokens share the same backend protocol. Even the DApp container can be reused simply by switching out the contract address.

What would mobile apps of tomorrow look like?

The mobile apps of tomorrow will be built on top of cryptographic protocols that connect to decentralized networks such as Bitcoin and Ethereum, instead of connecting to a centralized network like Facebook.

In this world, we may need to rethink the very notion of what a “mobile app” is, and how to build one without compromising a user’s security when their identity is baked into the protocol.

1. The Rule of Least Power

There is a concept called “The Rule of Least Power”, coined and implemented by Sir Tim Berners-Lee as the fundamental design principle for the World Wide Web.

The idea is that simple is superior to complex in a potentially dangerous environment, such as the Web. The rule states that a “descriptive” language is stronger than a “procedural” language:

“…given a choice among computer languages, … the less procedural, more descriptive the language one chooses, the more one can do with the data stored in that language.

Also, a simple language is more secure than a complex one:

“… Less powerful languages are usually easier to secure… Because programs in simpler languages are easier to analyze, it’s also easier to identify the security problems that they do have”

Summary: Simple is more powerful than complex. Simple is more secure than complex. A wild wild west environment like the world wide web should be implemented with the simplest language possible, such as HTML.

“a variety of characteristics that make languages powerful can complicate or prevent analysis of programs or information conveyed in those languages, and it suggests that such risks be weighed seriously when publishing information on the Web. Indeed, on the Web, the least powerful language that’s suitable should usually be chosen.

Fast forward to today, and we’re dealing with a new Internet over which we send real money and where we want our apps to securely function with minimal maintenance long after their original creative teams move on. The “Rule of least power” design principle has never been more relevant than today.

This is why I believe a “less powerful” standardized markup-driven approach is better for building mobile apps on crypto-protocols, instead of building “powerful” apps that end up being more of a liability in the long run.

2. Fabric of the Decentralized Internet

As a protocol developer, your goal shouldn’t be to build a single monolithic app — you’re not an “app developer”. Instead, your focus should be 100% on making it easy for anyone to embed your protocol into their apps and open it up as widely as possible.

Hypothetical example: Augur

In the hypothetical example above, Augur has multiple smart contracts that make up the entire experience. The Augur team *could* go for building a single all-in-one app themselves, but what good would that do for decentralization?

The cool thing about building a protocol is that you can let anyone build their own interpretation of it, optimized to specific needs. The adoption should be determined by the free market. Building a “reference” implementation might be good, but that shouldn’t be your goal. The goal is to make it as easy as possible for your community members Alice, Bob, and Carol to build their own custom apps on top of it. The best way to do that is to write your app in a language that’s as forkable as possible, which in my to my eyes is a markup approach.

3. Monolithic vs. Mashup

Let’s take this even further.

Today, we have only a single dominant protocol — HTTP. However, the mobile apps of tomorrow will be multi-protocol.

The current paradigm of “mobile apps” is all about building a single monolithic app which the developer has 100% ownership over. This was a natural choice in a “client-server” world where it is assumed that the developer of a mobile client also owns the server. For example, Facebook app connects to Facebook server, Twitter app connects to Twitter server, etc. In that world, it totally makes sense for the client developer to build a monolithic app, and that’s what we’ve been accustomed to until now.

But in the age of decentralized protocols, one app can be powered by multiple protocols. One app can be a “mashup” of multiple ownerless protocols.

There is no “Augur app”, “0x app”, “Decentraland app”, etc. That’s an old way of thinking.

Instead there will be apps that use all of these protocols together within a single app.

4. Security through Dependency Free Implementation

The problem is, achieving all this is not as easy as it sounds. We’re dealing with real money here and integration is surely not as easy as running npm install. The conventional approach for building any kind of app today is:

  1. Tightly coupled modules
  2. With complex dependencies
  3. That assume a monolithic centralized app

This has been great for the age of centralized and trusted app providers, but in the world of decentralized and trustless protocols, it’s too risky because so many things can go wrong on the app developer side no matter how secure the protocol is.

After all, it is no secret that highly coupled dependencies can introduce a cascade of security vulnerabilities:

The best way to avoid this problem is to… avoid dependencies, and simplify!

As Bruce Schneier preaches in the article, you can’t secure what you don’t understand.

Based on these assumptions my proposal for building mobile apps is to build them as sandboxed, loosely coupled, dependency-free containers:

  1. Sandboxed: Each view is a sandboxed container just like a web page. Each view’s state doesn’t carry over to another “page” unless explicitly stated (View A and View B are completely separate)
  2. Loosely coupled: Each view is loosely coupled through inter-container protocols ($href for moving forward, and $ok for returning backward) and sometimes app-wide shared global variables.
  3. Dependency free: All views are completely self contained and dependency free, so one view can be integrated into multiple different apps without having to rewrite anything (You can turn this app into a completely different app simply by changing the href attribute to point to View C instead of View B)

This design principle makes sure that:

  1. One implementation bug can’t cause a domino effect leading to a huge disaster. (See leftpad)
  2. Apps can be “upgraded per view” without having to rebuild the entire app. Without this, one bug will mean every app developer who’s used the protocol will need to rebuild and update their apps immediately, which will never happen.
  3. The protocol developer can distribute their “app” as a secure atomic unit that app developers can easily embed into their apps (instead of as a monolithic app)

5. Seamless Integration of HTML into Native App

If you’re a developer, you’re probably aware of the whole battle between “Native vs. HTML5”. Proponents of these two factions have been fighting over which will become the single dominant platform for building mobile apps.

A better way to look at this problem is to think of how to blend them together so seamlessly that the integration is almost unrecognizable and therefore the question becomes irrelevant.

The rule of thumb is to build apps as natively as possible, but for certain cases where it makes sense to integrate HTML components — such as graphic-heavy visualization —you should be able to do so in the most seamless manner.

Imagine building a simple game app, you could:

  • Build the graphic heavy parts of your game with an HTML5 based game engine
  • But use native views for the rest of the app

And this is only possible when you move away from the mindset of “only one approach wins” and focus on integrating the two in the best way possible. Below are examples of how native components and HTML components blend in perfectly together, WITHOUT having to modify the HTML at all:

I talk about this further in another article:

Interested?

In this article, I explained how I took an existing web3 DApp and turned it into a native mobile app. The key takeaways from the approach:

  1. Markup-driven
  2. Sandboxed Views
  3. Loosely coupled through protocol

The first two is similar to how web browsers work, and the third is like how microservices work. Combining these I have proposed a unique architecture for building secure mobile apps.

The purpose of this post was NOT to claim this is the “ultimate solution”, but to propose a mental framework for thinking about this topic, as well as an actual functional implementation to support the hypothesis.

I think this topic of “what would the frontend in the age of decentralized protocols look like?” is not really talked about much in the community because:

  • Most people are focused on building the backend, and people don’t really want to have to worry about centralized platforms.
  • Most of those who HAVE thought about it are building centralized products.

But mobile apps are inevitable if you want mainstream adoption, and we need to start thinking differently about how an app will work in the blockchain world.

I am excited about decentralized technologies because it’s very aligned with my view of the future, and am planning on exploring this field further. Here are some of the themes I am thinking of:

  1. Take the app I’ve built and turn this into a “plug-and-playable” framework (so all you need to do as a developer is “embed” your DApp with 3 lines of JSON, for example)
  2. Create high level overlay frameworks on top, for example ERC20 or ERC721 token specific agents.
  3. Support other chains: Bitcoin, etc. (Suggestions welcome)
  4. Look into integration with hardware wallets like Ledger and Trezor.

If you have any suggestions or feedback, please share. Also, stay in touch if you’d like to follow the journey. I’d love to hear from you!

Where to find me:
Chat with me on Slack: https://jasonette.now.sh/
Follow me on Twitter: https://twitter.com/gliechtenstein
Follow me on Medium: https://medium.com/@gliechtenstein
Contribute to Jasonette on Github: https://github.com/Jasonette
Follow Project Jasonette on Twitter: https://twitter.com/jasonclient
Subscribe to Jasonette Newsletter: https://docs.jasonette.com/#mc-embedded-subscribe-form
Topics of interest

More Related Stories