Home

Awesome

JSON dApp Environment (JDE)

JDE can be thought of as a "Programmable" transaction builder for the Ergo blockchain, with JSON being the programming language.

Using in your own project

Add the following to build.sbt

  libraryDependencies += "io.github.ergoplatform" %% "ergojde" % "1.0"

What can it do?

Recall that in an Ergo dApp, building a transaction usually involves a combination of the following tasks:

  1. Get some unspent boxes from the blockchain with some specific properties (such as with a given address and/or containing a given NFT).
  2. Extract data from those boxes (tokens, registers) and compute some values using the data.
  3. Define output boxes from the above data and create a transaction request to get an unsigned transaction.
  4. Optionally Use a wallet software (such as the Ergo node) to sign the transaction.

JDE is designed for Steps 1-4. Step 4 is done via a connector to an Ergo node.

Example Usage

JDE is used in Ergo UrlWallet to fetch Erg/USD rate from Oracle pool 1.0 using the following script:

{
  "constants": [
    {
      "name": "oraclePoolNFT",
      "type": "CollByte",
      "value": "011d3364de07e5a26f0c4eef0852cddb387039a921b7154ef3cab22c6eda887f"
    },
    {
      "name": "poolAddresses",
      "type": "Address",
      "values": [
        "NTkuk55NdwCXkF1e2nCABxq7bHjtinX3wH13zYPZ6qYT71dCoZBe1gZkh9FAr7GeHo2EpFoibzpNQmoi89atUjKRrhZEYrTapdtXrWU4kq319oY7BEWmtmRU9cMohX69XMuxJjJP5hRM8WQLfFnffbjshhEP3ck9CKVEkFRw1JDYkqVke2JVqoMED5yxLVkScbBUiJJLWq9BSbE1JJmmreNVskmWNxWE6V7ksKPxFMoqh1SVePh3UWAaBgGQRZ7TWf4dTBF5KMVHmRXzmQqEu2Fz2yeSLy23sM3pfqa78VuvoFHnTFXYFFxn3DNttxwq3EU3Zv25SmgrWjLKiZjFcEcqGgH6DJ9FZ1DfucVtTXwyDJutY3ksUBaEStRxoUQyRu4EhDobixL3PUWRcxaRJ8JKA9b64ALErGepRHkAoVmS8DaE6VbroskyMuhkTo7LbrzhTyJbqKurEzoEfhYxus7bMpLTePgKcktgRRyB7MjVxjSpxWzZedvzbjzZaHLZLkWZESk1WtdM25My33wtVLNXiTvficEUbjA23sNd24pv1YQ72nY1aqUHa2",
        "EfS5abyDe4vKFrJ48K5HnwTqa1ksn238bWFPe84bzVvCGvK1h2B7sgWLETtQuWwzVdBaoRZ1HcyzddrxLcsoM5YEy4UnqcLqMU1MDca1kLw9xbazAM6Awo9y6UVWTkQcS97mYkhkmx2Tewg3JntMgzfLWz5mACiEJEv7potayvk6awmLWS36sJMfXWgnEfNiqTyXNiPzt466cgot3GLcEsYXxKzLXyJ9EfvXpjzC2abTMzVSf1e17BHre4zZvDoAeTqr4igV3ubv2PtJjntvF2ibrDLmwwAyANEhw1yt8C8fCidkf3MAoPE6T53hX3Eb2mp3Xofmtrn4qVgmhNonnV8ekWZWvBTxYiNP8Vu5nc6RMDBv7P1c5rRc3tnDMRh2dUcDD7USyoB9YcvioMfAZGMNfLjWqgYu9Ygw2FokGBPThyWrKQ5nkLJvief1eQJg4wZXKdXWAR7VxwNftdZjPCHcmwn6ByRHZo9kb4Emv3rjfZE"
      ]
    }
  ],
  "auxInputs": [
    {
      "address": {
        "value": "poolAddresses"
      },
      "tokens": [
        {
          "index": 0,
          "id": {
            "value": "oraclePoolNFT"
          }
        }
      ],
      "registers": [
        {
          "num": "R4",
          "name": "rateUsd",
          "type": "Long"
        }
      ]
    }
  ],
  "returns": [
    "rateUsd"
  ]
}

What can it be compared to?

JDE is similar to Ergo-AppKit and the Headless dApp Framework (HDF) in that all three are tools to interact with the Ergo blockchain. Developers can use these tools to read data from the blockchain, compute using that data and optionally create transactions to be broadcast. Each tool requires the developer to "program" in some language.

Users of AppKit will usually write Scala code (although AppKit supports many other languages). HDF users will need to write Rust code. JDE users will have to write JSON, which is arguably the easiest to learn of the three. The downside of using JSON is that JDE scripts are more verbose than the other two languages. For example, the JDE equivalent of Scala's a = b + c is {"name":"a", "left":"b", "op":"add", "right":"c"}.

The folder sample-scripts contains some sample JDE programs.

Example: Minting Reserve Coins

The following steps will explain how to mint Sigma USD reserve coins.

This will send the mint transaction and print the transaction id.

For minting stable coins, use the script sample-scripts/mintStableCoinAdvanced.json.

Core Capabilities

The following are the core capabilities of JDE:

  1. Reading data from the blockchain. As an example we could use JDE to get the following data:

    (a) The current ERG/USD rate determined by the ERG/USD oracle.

    (b) The Sigma-USD bank's Erg balance and stable-coins in circulation.

    The data must be stored in an unspent box (JDE cannot access spent boxes).

  2. Computing using the above data and returning the result. For example:

    (a) The current reserve ratio of the Sigma-USD bank.

    (b) The current rate of Sigma-USD reserve and stable coins.

  3. Create a Transaction Template for a transaction using the above values such as one for minting some Sigma-USD reserve coins.

Transaction Template

An Ergo unsigned transaction (UT) is a tuple (inputs, data-inputs, outputs) such that the following hold:

For brevity, we represent boxes using boxIds. Thus, a UT is a tuple (input-boxIds, data-input-boxIds, outputs) such that the above conditions hold.

A transaction template (TT) is similar to an unsigned transaction in that it is also a tuple (input-boxIds, data-input-boxIds, outputs). However, none of the above conditions are required to hold in a TT.

For a given script, JDE outputs a TT along with some metadata such as the sum of nano-ergs and tokens in the inputs and outputs. In particular, JDE does not ensure that the input and output nano-ergs/tokens are conserved. The metadata can be used by the wallet software to create a UT from the TT by adding a fee output and optional funding and change outputs. An example of this is in the KioskWeb wallet.

On the other hand, we can also write JDE scripts where the output TT is also a UT (by specifying funding, change and fee outputs in the script itself). In this case, the TT can be directly used for generating the final signed transaction. An example of such a script is the advanced mint reserve-coin script.

Running JDE

Depending on the use-case and the actual script, JDE has the following entry-points (modes).

Currently, there are two ways to run JDE: via a CLI and as a web-service.

Before going further, ensure you have cloned the repo using git clone https://github.com/ergoplatform/ergo-jde.git and have Java and SBT installed.

Using CLI

In order to use the CLI, first create a fat jar using the command sbt assembly. A jar called jde.jar will be created in the folder target/scala-2.12.

The CLI supports all 4 modes of operation, with the default being "Compile".

Using the web service

Unlike the CLI, the web service currently only supports the Compile mode. The web-service can be run in two ways.

  1. Using the embedded web-server (Jetty): This is the easiest way and should be used for development mode.

    • Open SBT console within the root project folder using the command sbt.
    • In the SBT shell issue the command jetty:start.
    • The service will start listening on http://localhost:8080
  2. Using an external J2EE web-server.

    • Generate the war file using the command sbt package. The war file will be created in target/scala-2.12 folder.
    • This file can be run under any standard J2EE web server. The service will start listening on the port configured in the web-server

In both cases the endpoint /compile will be exposed for sending requests. The endpoint accepts both GET and POST requests where the body contains the script code. The following shows how to call the POST endpoint using cURL.

curl --data @sample-scripts/getStableCoinInfo.json http://localhost:8080/compile

The following is a sample response from the above call:

{
  ...
  "returned" : [ {
    ...
    "name" : "reserveRatioPercentIn",
    "value" : "403"
    ...
    "name" : "rate",
    "value" : "2506549"
  } ]
}

The above returns the current reserve ratio of the SigmaUSD bank along with the current stable-coin rate.

Writing JDE Scripts

A user interacts with JDE using a structure called a Program (source), a JSON-encoded script defining the following primary components:

  1. Inputs: These contain instructions to search for boxes that will form the inputs of the transaction.
  2. Data-Inputs: These contain instructions to search for boxes that will form the data-inputs of the transaction.
  3. Outputs: These contain instructions to construct boxes that will form the outputs of the transaction.

A JDE program can also have other components such as:

  1. Auxiliary inputs: These contain instructions to search for boxes whose data we need to use in computation but such boxes need not be included in the transaction. As an example, the voting protocol of Sigma-USD requires R5 of the ballot boxes to contain the boxId of the update box. However, the update box itself is not used in the voting transaction. In this case, the update box will be specified as an auxiliary input.

  2. Post-conditions: These are used to ensure that certain conditions are satisfied after the final step. As an example, for Sigma-USD, we can have post-conditions to check that the reserve ratio is between the specified values.

  3. Branches: These can be used to handle if-then-else cases. Note that JDE does not support loops.

  4. Constants: These can be used to define constants (such as the Sigma-USD bank address or NFT id) for later use.

  5. Returned values: These can contain values that the end-user wants, such as the current Sigma-USD stable-coin rate.

  6. Binary and unary operations: These define operations to apply on any of the values obtained earlier.

Each of the above components are optional. If the outputs are not specified then the transaction template won't be created.

Unspent boxes can be searched by address and/or box-id. With box-id, there can be at most one box, so we can unambiguously define a box. However, when matching with address, there can be multiple boxes. These are handled as follows:

The folder sample-scripts contains several sample JDE programs. The tests contain more examples.

See this document for the detailed semantics of JDE programs.