Answering the call: Distributed Twitter made easy!

Jack Dorsey, the CEO of Twitter sent a series of tweets at the end of 2019 saying that Twitter is researching in moving towards a decentralising version of Twitter :

 

As part of these tweets, Jack lays out his reasons for moving towards the decentralisation of Twitter and Social Media. The first reason Jack mentions is the challenges Twitter are facing with their current centralised solution, specifically that applying global policy to a centralised data set is unlikely to scale:

Having a centralised solution for a global product is challenging in today’s ever changing world. How do you ensure that your data meets the standards set by the multiple jurisdictions in which you operate in? How do you ensure that you are not applying the policies of one jurisdiction to the data of another jurisdiction? What do you do when you have conflicting policies to enforce?

From a user’s perspective, once you post a message on Twitter (or other Social Media platforms) you lose all control over that content - you don’t know how your content is monetised, to whom your content is sold to, for what purpose was your data sold, etc. 

Benefit of Daml and Smart Contracts

Daml is a purpose-built smart contracts platform aimed at creating distributed applications with strong privacy and integrity guarantees. Daml applications can run on multiple DLTs, blockchains and databases without requiring any changes - write once, run anywhere. You can use your favorite programming stack (React, JavaScript, Java, etc.) to work with the Daml smart contract layer.

Daml uses the concept of “parties” to represent actors which can be individuals or entities. The disclosure and distribution of data is controlled by the roles these actors play. Actors can have rights (can take actions), be obligable (are accountable for the data they create), and be observers (they can see but not have any obligations or rights). 

Since the workflows we define in Daml can run on databases and blockchain alike, developers and business analysts need not think about the underlying platform intricacies. They can instead focus their energies on defining the business logic, which will automatically control the distribution and disclosure of data that the workflow generates. Using a chess analogy, focus on winning the game, not on negotiating the rules and setup of the board.

Scope

In this blog post, we’re going to focus on providing the minimum functionality (ie. a Minimum Viable Product) which provides the user with full control over their profile and the content they create. We’re going to use Daml to model the Smart Contracts and explicitly define what actions each party can perform. Since we’re using Daml we can write the application once, test it using the sandbox (which comes with Daml) and later run the application using our DLT of choice (which will be covered later in a blog post!). The frontend will be written in React, using the Daml Javascript library used to connect to the ledger.

Before diving into some of the implementation details, here’s a video showing the full functionality of the prototype:

Time for some Smart Contracts!

Central to providing the user with more control over their profile and content is the user profile. Lets create a basic user profile which allows the user to :

  1. Be the owner to their profile and allows them to maintain it;
  2. Accept or reject requests from other users to follow them;
  3. Create posts in the system;

We also need to provide a mechanism for users to find each other in the system :

The ‘signatory’ specifies which parties consents to the creation of a contract. On our contract, we only require the consent of the user. However, other parties must be able to view this contract (otherwise this won’t be a very social network!), which is where `observer` comes in. We’ve specified that other users who have made a request to follow a user may view the contract and also a ‘userDirectory’ party. The ‘userDirectory’ party will allow users to find each other via the front-end public user directory and thus they can make a request to become a follower of a user. This user will be a specific read-only user specifically for this public user directory. Also, we define a key (the username) which allows us to fetch this contract directly a defined key which we will use from the front-end to lookup this contract.

To enforce the observers have a read-only view of this contract, we simply don’t provide any choices for them to perform. That was easy! 

Let’s define the choices that only the owner of the contract (ie, the user) can perform against this contract:

The “controller username can” syntax allows us to explicitly specify the set of parties which may modify our contract and the modifications they can make. In our case, we want to limit the choices to the owner of the contract (ie, the end user), meaning no other party will be able to modify our contract. 

Some of the content in the choice’s have been left out for brevity, please take a look at the open source repository for more details on the implementation.

Interacting with our new models

For the front-end of our “Distributed Twitter” application, we are going to use the React framework (and Typescript). Thankfully, Daml provides us a set of libraries which provides a set of functionality to create smart contracts, execute choices, streaming, etc. for multiple languages.

In order to get started with interacting with the ledger, lets create Typescript representations of our models and choices. Luckily, Daml can do this for us via the command :

Running this command will generate all the boilerplate code of our Daml model templates specified earlier in the specified language of choice, in this case Javascript/Typescript. It’s also possible to generate code in other languages such as Java and Scala (please see the docs for more information).

For example, this command will generate the following type in Typescript based of our user defined earlier in Daml :

Constants relating to the choices which may be exercised against a given contract in Daml are also generated - This greatly simplifies the exercises of choices :

To create a new contract on the ledger, we simply execute the following :

We have our first smart contract on the ledger in only a few lines of code! We used the ‘useLedger’ React hook to get an instance of the ledger and ‘useParty’ to get the current user connected to the ledger. To create the contract on the ledger, we call the ‘.create’ function on the ledger instance with the target contract type with the details of the contact we wish to create.


We have our first smart contract on the ledger in only a few lines of code!

Now let’s modify this contract by exercising a choice defined against this contract :

We use the ‘exerciseByKey’ function which allows us to exercise a choice against an existing contract, identified by its key. Our User contract is identifiable by key via the ‘username’ of the contract, so providing this along with the choice we wish to call and the parameters to the choice (in this case, the updated ‘User’) we can modify the contract.


This is the UI for updating a user

We’ve seen how easy it is to create contracts and modify them (via choices), what about viewing contracts? Of course the Daml library provides functions to retrieve contracts from the ledger! The React library contains React hooks which allow us to stream changes directly from the ledger which means we can update our UI without having to refresh the page! 

This will stream all the User contracts which you can observe, which will be your own user contract. In the case of the public user directory, all User contracts are displayed in a read-only view. Any changes to the contract set will update the stream and React will re-render the UI to reflect the change. It’s also possible to provide additional parameters to the Daml React hook ‘useStreamQuery’ to filter on a subset of contracts.

Here’s some more screenshots from the prototype - feel free to explore the implementation of the prototype here at our open source repository:


This is a follow request from a user


This is a reply to a post


A user's view of their profile


A comment thread

Conclusion

In conclusion, we’ve learnt how simple it is to use Daml to create Smart Contracts and how to return back control and ownership of data back to the end user. We’ve also learnt how to create, modify or view these contracts from another layer (in our example, the UI layer) and how Daml takes care of all boilerplate code and provides features to make it simple to interact with the underlying ledger.

Please take a look at the open source repository for further implementation details and all pull-requests are welcome:

 

Check the open source repository

 

Also check this application in the OpenWork website:

 

Check the OpenWork Feed