3. Setup and Run the example

Now that we have in mind the overall dApp architecture, we can do a walkthrough of the necessary steps to turn on every service needed to get the dApp running. From a top view, we need to setup and run the server and client sides. In the server side, we will compile and run the PAB and Budget service. For the Indexer service we will use a public instance of Blockfrost, so we just need to get an API token and do some minor configuration. The client side will be in charge of running the web page engine.

We must start by cloning three repositories: the joinplank patched plutus-apps, the budget service and the complete dApp implementation:

  • git clone git@github.com:joinplank/plutus-apps.git

  • git clone git@github.com:joinplank/plutus-budget-service.git

  • git clone git@github.com:joinplank/cardano-e2e-example.git

In summary, we must have the following folder structure:

.
├── cardano-e2e-example
│   ├── backend
│   └── frontend
├── plutus-apps
└── plutus-budget-service

We’ll see how to setup and run the example using docker, or installing everything on the local machine.

3.1. Docker

The easiest way to have everything running doing a minimal configuration is by using docker. We have docker files for the backend, frontend, and budget-service. The instructions for running this last service can be found on the plutus-budget-service/README. Next we will see how to use a public deployed instance of this service.

Using docker-compose we build and run the other two services. We just need first to configure which instances of the indexer and the budget-service we will use. Everything about the indexer can be found in the coming subsection. We setup the budget-service by setting the environment variable REACT_APP_BUDGET_URL on the cardano-e2e-example/frontend/.env, with http://escrow.joinplank.com:3001/. After that, we just execute:

$> docker-compose up --build

The docker-compose building will take several minutes. Once everthing is running we can access the dApp on the url http://localhost:3000. In case we don’t want to use docker, we can install everything locally, as we explain next.

3.2. Local

3.2.1. Server side

We will use Nix for compiling and running the services. The flow will be as follows: enter the Nix environment, navigate to the corresponding folder, compile and run.

The first step is to install Nix from here. Second, we must follow this steps to set up the binary caches provided by IOHK, so we can speed up a lot the building process. Generally, we just need to edit /etc/nix/nix.conf by adding the following lines:

substituters = https://cache.iog.io https://cache.nixos.org/
trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
extra-experimental-features = nix-command flakes

Now, we must get inside the plutus-apps repository folder, and checkout the release corresponding to this particular commit:

$> git checkout a58d3a1934a4a3788da7815540a892dfe417b3bb

Then, we must run

$> nix-shell

to install all the needed dependencies and get inside the development environment. From this environment we will compile and run the services. The first time is going to take some minutes. If the process succeeds, you will get a new prompt indicating that you are effectively inside a Nix environment. From now on we will assume we are always inside this environment.

Indexer/Blockfrost

We will use a public instance of Blockfrost, so we must get a token key from its website. Once we have this token, inside the backend folder we have the config folder where we can find the blockfrost-token-preprod file, we will put the token there. In this particular example, the token corresponds to the preprod testnet:

$> cat config/blockfrost-token-preprod
preprod8kzHTV4w3E4WgpIZ9tpqY0YvuPwCAuht

This file will help us complete the configuration of the PAB.

The advantage of using Blockfrost is that we don’t have to setup and sync our own indexer, but if Blockfrost is not an option, we can setup and run the plutus-apps indexer.

Budget

This service allows us to evaluate Plutus scripts to know the memory and CPU execution units. First, inside a Nix environment, we must get into the plutus-budget-service folder and run:

$> cabal build budget-service

Then we can turn on the service with:

$> cabal run budget-server -- --config configurations/preprod.json

Here we are using the preprod configuration of the service placed in configurations/preprod.json. If everything goes well, we should get:

$> cabal run budget-server -- --config configurations/preprod.json
Starting budget-service at port: 3001
Quit the service with CONTROL-C.

We can check that everything is working using curl to call the evaluate endpoint of the service with the example we can find in the root folder:

$> curl -X POST localhost:3001/evaluate -H 'Content-Type: application/json' -d @example.json | jq
{
  "Right": {
    "Mint:0": {
      "exUnitsSteps": 422176029,
      "exUnitsMem": 1396682
    },
    "Spend:3": {
      "exUnitsSteps": 466510658,
      "exUnitsMem": 1549708
    },
    "Spend:0": {
      "exUnitsSteps": 1120532675,
      "exUnitsMem": 4164373
    }
  }
}

PAB

The PAB will run the off-chain code for building unbalanced transactions, using the indexer for querying the blockchain. First, we need to get into the backend folder to compile everything with cabal build escrow-pab. This will take some minutes the first time.

To run this service, we will use the pab-config-preprod.yaml configuration file present in the backend/config folder, so we must be sure everything is correctly setup there. This file has a lot of settings, but the relevant ones for us are the Blockfrost configuration, the wallet mode, the database, and the general PAB service.

For the Blockfrost configuration, we need to be sure we have correctly setup the path to the file we created before with the API token.

blockfrostConfig:
  bfTokenPath: ./blockfrost-token-preprod

Because we are using the PAB just for building unbalanced transactions we need to use the remote wallet approach:

walletServerConfig:
  tag: RemoteWalletConfig

For the internal PAB database the quickest setting is to use SQLite:

sqliteDB:
  dbConfigFile: "pab.db"
  dbConfigPoolSize: 20

We also have the option of connecting to a PostgreSQL database.

Finally, for the PAB service general configuration, the important settings for us are the baseUrl where we can change the hosting options, and permissiveCorsPolicy that must be set to True:

pabWebserverConfig:
  baseUrl: http://localhost:9080
  staticDir: plutus-pab-client/dist
  permissiveCorsPolicy: True
  endpointTimeout: 5
  enableMarconi: False

Once everything is compiled we must create the database:

$> cabal run pab -- --config config/pab-config-preprod.yaml migrate

and start the PAB:

$> cabal run pab -- --config config/pab-config-preprod.yaml webserver
[pab:Info:15] [2023-01-01 00:00:00 UTC] {"contents":{"contents":{"tag":"RestoringPABState"},"tag":"SMultiAgent"},"tag":"PABMsg"}
[pab:Info:15] [2023-01-01 00:00:00 UTC] {"contents":{"contents":{"contents":0,"tag":"PABStateRestored"},"tag":"SMultiAgent"},"tag":"PABMsg"}
[pab:Info:15] [2023-01-01 00:00:00 UTC] {"contents":{"contents":{"contents":9080,"tag":"StartingPABBackendServer"},"tag":"SMultiAgent"},"tag":"PABMsg"}

We can use curl again to check that everything is working by hitting the fullreport endpoint of the PAB:

$> curl -X GET localhost:9080/fullreport -H 'Content-Type: application/json' | jq
{
  "chainReport": {
  "annotatedBlockchain": [],
  "transactionMap": [],
  "utxoIndex": {
    "getIndex": []
  }
},
 "contractReport": {
   "crActiveContractStates": [],
   "crAvailableContracts": []
 }
}

Also, we can access the swagger through localhost:9080/swagger/swagger-ui.

3.2.2. Client side

The client side, as we mentioned, is going to run the dApp webpage service. In contrast with the server side, we don’t need a particular environment, but we need to ensure we are using node 16.x version, which is as simple as doing nvm install 16.14.2 and then nvm use 16.

Inside the frontend folder we run npm install, and before making npm start we need to setup the .env file where we setup the conection to all the services of the server side.

REACT_APP_PAB_URL='http://localhost:9080/api'
REACT_APP_BUDGET_URL='http://localhost:3001'
REACT_APP_BLOCKFROST_API_KEY='preprod8kzHTV4w3E4WgpIZ9tpqY0YvuPwCAuht'
REACT_APP_BLOCKFROST_URL="https://cardano-preprod.blockfrost.io/api/v0"
REACT_APP_LOG_LEVEL=DEBUG

Once we run npm start a browser webpage should prompt with the home page of the escrow dApp.