This section presents how to create and setup a DApp's User Interface (UI) project using React and Beacon's DApp/wallet interaction.
Any framework is suitable to create a DApp application as long as a Tezos library is available for it. We present here how to create a web DApp with React.
The choice of the React framework depends on the objective and the size of the application; typically a framework like Next.js is suited for large applications with needs for server side rendering. We are choosing create-react-app for its simplicity to create simple client-side & single-page applications: it installs and configures the whole pack of required bricks (webpack, babel, ...)
It is strongly recommended to use TypeScript language as it will greatly shorten and ease up the development cycle. Its typed aspect makes that many errors are detected at compilation time (ie. at the time of writing code) rather than later at execution. It just doesn't make sense to developp with untyped languages when you think of it ...
Project templates configured with TypeScript are available with most UI frameworks. The following command uses
create-react-app template with TypeScript:
npx create-react-app my-dapp --template TypeScript
This creates the
my-dapp project. More information may be found here
While it is always possible to interact directly with the Tezos endpoint's RPC API, it is more than recommended to use a dedicated library that will wrap all services in high-level development services and take care of all the low-level Tezos protocol details.
In the context of web DApps for Tezos, the main library is Taquito:
npm install @taquito/taquito
Taquito uses official cryptographic packages (aka libraries). Some of these packages relies on nodejs packages designed to run on the back-end side (server side, not in a browser). These packages are
os. As a result, the default build process fails; it is then necessary to map these packages to their front-end counterparts in the build process:
Follow instructions available here to solve build issues.
As a comment,
create-react-app uses webpack (version 5) to bundle all resources as static web assets. It is then necessary to use the
react-app-rewired package as described in instructions above, to be able to provide a customized webpack configuration without ejecting the react app.
A DApp needs to interact with a wallet to sign operations (transfers, calls to a smart contract, ...). Many wallets are available on Tezos (Temple, Kukai, Umami, ...). It is common practice to interact with them all via Beacon that implements the interaction standard TZIP-10 between a wallet and a dApp, as it greatly reduces the integration effort with wallets.
npm install @taquito/beacon-wallet @airgap/beacon-sdk
The main drawback of Beacon is the lack of control over the UI elements (typically the wallet selection popup), which can be a no-go if you want a tight control of the DApp L&F. In that case, each wallet needs to be integrated separately.
A plug-and-play constate context for Beacon services
disconnect is available
When interacting with a contract (read and write), it is strongly recommended to use its generated TypeScript binding, that is a typed high-level TypeScript interface. It greatly reduces the effort to call a contract, read its storage and the number of runtime errors, as the compilier and LSP guides you through the contract interface.
TypeScript bindings may be obtained with the following Completium CLI command:
completium-cli generate binding-dapp-ts mycontract.arl > mycontract.ts
Bindings generation is also available for Michelson (.tz) files.
The generated binding interface relies on two packages:
npm install @completium/dapp-ts @completium/archetype-ts-types
With React applications, it is strongly recommended to setup contexts for application data (settings, UI states, ...) in read/write modes with a dedicated package like constate or redux. This is preventing from awkward spaghetti code of passing components states and data through large hierarchy of components.
The DApp example presented here is using constate for its lightweight aspect.
npm install constate
Taquito and Beacon must be singletons, hence there are wrapped as contexts (with constate) to make them available to UI components. The same stands for the contract bindings.
The main 4 blockchain-related contexts are provided as plug-and-play code:
Blockchain-related DApp settings
Provides Taquito's Tezos Toolkit hook
connectand wallet address services
Provides contract binder
Schema below illustrates the module and package architecture of the DApp and their interactions:
- Changes in
Contextsdata automatically redraw
UIcomponents that use them (React + constate hook mecanism)
UIinteract with contract via
Contextsuses Beacon's services to connect to a wallet
- Taquito's Tezos toolkit uses Beacon as transaction signer
@completium/dapp-tspackage services to interact with blockchain
@completium/event-listenerto listen to emitted events
The typical file structure of the react project is presented below:
│ ├── favicon.ico
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
│ └── ...
│ └── ...
│ └── ...
Note that 4 directories are created under
bindings: generated contracts bindings
routes: page UI components managed by a route manager (for example
components: other UI components
contexts: hooks providers