Building Your First dApp

Provenance Blockchain Foundation
Provenance Blockchain
10 min readOct 10, 2022

So you want to create some service that can provide value utilizing the Provenance Blockchain in exchange for a small fee? Fine, let’s do that. Because everyone loves buzzwords, let’s build a ✨dApp

What is a dApp?

If you are reading this article, then you likely already have a basic grasp of the concept of a dApp, but here goes. A decentralized application (dApp), is an application that runs on a blockchain, as opposed to a traditional server or set of servers controlled by a particular entity. Now, you may be wondering why you wouldn’t just go ahead and use one of the many standard cloud services to build a regular ol’ webapp on. That is a fair question, so I’ll give you my opinion to do with what you will.

There are several main advantages that I see when choosing to build an app as a dApp:

  • With a minimal amount of code, we can build a system that can accept payments and records data without having to manage anyone’s private information, payment details, user accounts or other things that have to be dealt with sensitively. Shoot, we don’t even need to handle passwords, as the users of our app can sign off on actions using their own private wallet and all information we will be displaying is already publically visible on the blockchain.
  • We can host our entire application using a simple, cheap (free, even) frontend hosting, as the blockchain itself will be our backend.
  • You will receive some good (free, even) stares from family members when you tell them that you built a dApp.

Depending on what you are trying to build and the features entailed, you certainly may need to build something more complex that involves traditional server-side code. However, you can build out a surprising amount of functionality without this, and that is what we are going to do today.

What Should We Build?

For this example, we are going to walk through building a name-registration service to allow users to register human-readable and memorable (or not memorable, your choice) names to their account on Provenance Blockchain. After all, why would you want to go by pb1athr52jkdp6lk9vj40prengsvd5pkamzc9mggt when you could be koolhack3r_23? Ultimately, this is a very similar concept to the DNS system (DN System?) that allows us to visit websites by URL instead of the underlying IP address of a server somewhere. This name registration could then be utilized by other dApps to incorporate functionality like sending payments to someone directly by name instead of address, or as a smaller building block for other, more advanced, functionality.

What Elements do we Need?

We need a smart contract that can:

  1. Allow users to register a name with their account
  2. Extract a fee when names are registered within this service, in exchange for providing the service
  3. Expose query functionality allowing the ability to look up the address tied to a name, as well as list all names bound to a particular address.

We need a user interface that can:

  1. Allow a user to ‘login’ by connecting their Provenance Wallet (available for iOS, Android or as a Chrome Extension)
  2. Allow the connected user to register a name against their account (address corresponding to their wallet)
  3. List the connected user’s names (if any exist)
  4. Allow the user to look up the name/names bound to an address

The Contract

Provenance Blockchain smart contracts are relatively easy to get spun up on, just go learn Rust.

Or alternatively, skip that part and follow the ProvWasm Tutorial, which walks you through the step-by-step building and usage of a smart contract on the Provenance Blockchain. Another smart contract example can be found here in the how-to-provenance repo

The contract doesn’t need to do all that much, just store registered names on accounts using the Provenance Attribute Module, have some sort of lookup from name -> address for resolving addresses from names and then have entrypoints to expose this registration/query functionality. We don’t need to get into the nitty-gritty of how to implement each of these things within this particular blog post, but you can check it out here in the how-to-provenance repo.

The Frontend

Now, we aren’t out to build the most well-designed UI here, but I think we can get the basic functionality of registering/listing/searching names going in a usable manner. I will outline the general steps to create such an application, but the actual code for this example application can be found here. This will be a standard React application, and discussing React details is out of scope for this post.

To connect with the Provenance Wallet, we are going to use a library called walletconnect-js. So go ahead and do the npm i @provenanceio/walletconnect-js@latest dance. This will provide us with a few important things:

  1. A component for displaying the QR code to use for connecting to the mobile wallet (iOS | Android | Chrome)
  2. A React hook returning:
    a. A state object detailing the current wallet connection status/details
    b. A service for submitting messages to be wrapped into transactions and signed/submitted by the wallet.

Starting from a basic React skeleton application (created via Create React App or the like), we first need to provide the context for connecting to the Provenance Blockchain using the WalletConnectContextProvider component provided by walletconnect-js. This component needs to wrap the root of the application, or at least the section of your application where walletconnect functionality will be used. This context will provide the network to connect to (testnet/mainnet).

Next, we can create some basic button components that will trigger the walletconnect-js modal to display. These buttons just need to call the walletconnect-js service’s connect/disconnect methods as appropriate (with the current connection status determined by inspecting the walletConnectState.connected boolean provided by walletconnect-js). The QRCodeModal component provided by walletconnect-js must also be present somewhere in the DOM, with the state/service injected into it. This component will automatically show/hide the modal depending on the connection status and actions triggered by the connect/disconnect buttons we created.

Great, now that we can connect to a Provenance wallet, we can determine whether we are connected or not, and access the address of the account we are connected to by inspecting the walletConnectState object provided by the useWalletConnect hook. We can use this information to show/hide/alter various parts of our application as appropriate. In this example, we will just hide our main UI section when not connected, and show it once connected. Once connected, we will display some basic details about the connected wallet (address, hash balance, etc.) and list any names registered against this address.

Remember, by connecting a wallet we aren’t receiving any private key, password, or any other sensitive information from the user. We now just know the address associated with their wallet and have a mechanism for generating messages and prompting them to sign for them via their wallet, where they hold their own key.

In order to query the blockchain, we need another library wallet-lib that exposes javascript grpc service bindings for communication with a blockchain node via an Envoy Proxy (shakes fist at browser http/2 support). Again, party on with npm i @provenanceio/wallet-lib@latest. This library provides a context component called WalletContextProvider similar to the one provided by walletconnect-js that allows us to specify the url of the Provenance Blockchain node proxy and wallet url. Once we have wrapped the root of our application with this context, we can utilize the useWallet hook from this library to gain access to a grpcService that can be used for querying the chain to your heart’s desire.

Now that we have all the pieces to submit transactions to the user’s wallet and query various things on the Provenance Blockchain, we just have to put some actual application logic in place to make this useful. First, we will create a little service to facilitate resolving a contract’s address via name and submitting a query against a contract (see below). Please note that all code examples are snippets extracted from the linked files for brevity.

This service just provides us with a couple of wrapper functions around the generated grpc services from wallet-lib and constructs valid protobuf message payloads for querying the Provenance name/wasm modules and returns the results.

Next, let’s create a service for interacting with the name contract itself. This will give us the functionality to expose the query functionality from the contract (list/resolve/query names), as well as generate a message that can be submitted to the wallet for signing in order to bind a name to our address. Note that this service utilizes some little helper classes found here that simply serve to easily give us properly-formed json payloads for interacting with the name service smart contract.

If you will notice, the message we generate for registering a name with the contract also sets a ‘funds list’, which is where the fee required for registering a name is provided. This will result in those funds being transferred from your wallet to the contract’s registered fee_collection_address upon registration (remember, in order for this to all happen, you have to sign off on the transaction with your wallet and during that process the wallet displays the funds being sent in before you approve the transaction; we aren’t able to grab funds out of the user’s wallet all willy-nilly). The code detailing this fee collection can be found in the smart contract example here. So if you are the one who created/maintains this contract, this is how you can fund your efforts.

Great, now we have the pieces we need to perform all of the basic functions provided by the name service smart contract. All that is left to do is to slap a few components together to do all the things. Remember, we aren’t going for the most sophisticated UI here, this is just a quick and dirty demo of interacting with a smart contract and connected wallet. I’ll leave it up to you to do all this and more in a beautiful fashion.

Let’s start by resolving any names registered to the connected wallet’s address. This little function and useEffect hook ought to do the trick, querying the names for the connected address (if present, otherwise clearing the list if not connected). Note that we are simply using the useWalletConnect hook provided by walletconnect-js to determine the connection status/address.

We can then feed these names to some sort of list component so the user can view them.

Additionally, we can add a small form component where a user can enter a name they wish to bind to their address and submit this registration to their wallet for signing. We can accomplish this with this function (where the name is provided by user input, and the address is pulled from the useWalletConnect hook). Note that we are simply using the walletConnectService provided by walletconnect and feeding it the name register message as created (json encoded and then base64’d) via our NameContractService. We also have an opportunity to provide a simple description for display in the wallet when signing. As you can see, submitting a message for signing like this is really pretty straightforward, we are just gluing some pieces together here.

And now for a couple of other components to handle looking up an address by name, or listing names when given an address. Given that we have a couple different methods of querying the contract based on a name, let’s handle explicit searching in one component, and the substring style search in another.

I will continue to spare you the details of UI construction within this post, but here we can see a function to handle taking in a search value, and details on whether that term is an address or a name. By feeding this to our resolveName and/or listNames function(s), we can either list all names belonging to an address, or resolve a name to an address, and additionally list other names that are also bound to that resolved address.

Finally, to expose the substring name search provided by the contract, we can take in some search term and query the contract for it, like so.

Woo-hoo, we have successfully created a dApp for registering names against addresses on Provenance Blockchain! A version of this UI is hosted here on GitHub Pages, using this instance of the name service smart contract on Provenance’s testnet.

I find the concept of dApps to be quite interesting, as you can build out a useful bit of functionality relatively quickly and then this can be composed together with other dApps to create a greater whole. And because these dApps all operate on the Provenance Blockchain, and utilize your connected wallet (your keys, your crypto), they can interoperate and play together nicely, sometimes without even knowing that the other may exist.

PIERCE TREY

Pierce is a software engineer for Figure based in Bozeman, Montana. He works in the R&D group building out tooling to facilitate usage of the Provenance Blockchain within Figure, and exploring how to accomplish sometimes-harebrained ideas on-chain. Outside of work, he enjoys spending time with his family, playing stringed instruments, and lately somehow finds himself in a never-ending stream of house renovation projects.

--

--

Provenance Blockchain Foundation
Provenance Blockchain

The public open-source blockchain used by over 60 financial institutions. Billions of dollars of financial transactions have been executed on Provenance.