Step-by-Step dApp

Project Setup

To initiate the creation of a new React app using npx create-react-app, follow these steps:

  1. Ensure that you have Node.js and npm (Node Package Manager) installed on your system.

  2. Open your terminal or command prompt.

  3. Execute the following command:

npx create-react-app my-app

Replace "my-app" with your desired name for the React app. This command will establish a new directory named "my-app" and configure a basic React application structure within it.

  1. After the process completes, navigate to the newly created directory:

cd my-app
  1. Launch the development server:

npm start

This action will start the development server and automatically open your React app in a web browser. You can now commence building your React application by making changes to the files within the "src" directory.

Utilizing npx create-react-app presents a swift and straightforward method for initializing a new React project with all the essential configurations and dependencies, freeing you to concentrate on developing your app without concerning yourself with the initial setup.

Ethernity Cloud Runner package installation

To begin developing with the Ethernity Cloud Runner, you can easily set up your environment by installing the package using npm:

$ npm install @ethernity-cloud/runner --save

This command will install the Ethernity Cloud Runner package and save it as a dependency in your project. With the package installed, you're ready to start utilizing the Ethernity Cloud Runner functionality and explore its capabilities for your application development.

Ethernity Cloud Runner usage and integration

This comprehensive guide explains the seamless integration of the Ethernity Cloud Runner module into your React application, empowering developers to execute Python tasks. The following sections elaborate on the integration process:

  1. Import Statements:

    Begin by editing /src/App.js and by importing the essential modules and styles. Import ./App.css for styling, and crucially, include two pivotal modules from the @ethernity-cloud/runner package: EthernityCloudRunner, ECRunner and ECStatus.

    These modules are vital for interacting with the Ethernity Cloud Runner and defining the runner type.

import './App.css';
import EthernityCloudRunner from "@ethernity-cloud/runner";
import {ECEvent, ECRunner, ECStatus} from "@ethernity-cloud/runner/enums";
  1. Defining Code to be Executed:

    The Ethernity Cloud Runner allows users to execute tasks using different programming languages and frameworks. Currently, the runner supports two main templates: Python and Node.js. Users can define the code to be executed within these templates to perform specific tasks on the Ethernity Cloud ecosystem.

    Python Template:

    In the Python template, users can write their code in Python programming language.

    Below there is an example of Python code that returns

    str = "Hello World!";
    
    ___etny_result___("Hello, World!");

    Node.js Template: For those who prefer JavaScript, the Node.js template offers a powerful option.

    Below there is an example of Node.js code that computes the sum of two numbers:

    const string = "Hello World!";
    
    ___etny_result___(string);

    To use either template, users need to provide the code in the corresponding programming language that defines the specific task they want to execute. As you can see, the___etny_result___ function is specially used inside a Ethernity Cloud Runner tasks. When executing a task, this function allows the task code to send the result back to the Ethernity Cloud ecosystem.

    Because there is no output console of the code that is being process, this special function plays a crucial role in ensuring that the results of executed tasks are safely recorded and sent to the user performing the task request. For our example we are using the following nodejs code:

    const code = `___etny_result___("Hello, World!")`;

  2. App Function Component:

    Define the App function component, which plays a pivotal role in rendering the entire application.

function App() {
}

export default App;
  1. Execute Task Function:

Within the App function, define the executeTask function as an asynchronous function that triggers upon clicking the "Execute task" button.

const executeTask = async () => {
};
  1. Runner Initialization:

The first crucial step involves creating an instance of the EthernityCloudRunner. Initialize the runner by constructing:

const runner = new EthernityCloudRunner();
  1. Decentralized Storage Initialization:

Next, initialize the Ethernity Cloud Runner's decentralized storage by specifying the IPFS address where it will communicate with the IPFS network.

// this is a server provided by Ethernity CLOUD, please bear in mind that you can use your own Decentralized Storage server
const ipfsAddress = 'https://ipfs.ethernity.cloud:5001';
runner.initializeStorage(ipfsAddress);

For this integration, you have multiple options to initialize the storage:

  • Ethernity Cloud IPFS Server (Recommended for Development):

Utilize the default IPFS address 'https://ipfs.ethernity.cloud:5001' provided by Ethernity Cloud, which serves as an efficient option for development purposes. It ensures seamless initialization with the specified IPFS address, allowing you to focus on task execution without managing your own IPFS infrastructure.

  • Custom IPFS Server:

Alternatively, if you have your own IPFS server set up or prefer to use a different IPFS address, you can provide the desired IPFS address to the runner.initializeStorage(ipfsAddress) method. This option empowers you to leverage any IPFS infrastructure that suits your specific requirements.

  • Other Decentralized Storage Solutions:

Ethernity Cloud Runner offers the flexibility to integrate with various decentralized storage solutions beyond IPFS. While IPFS is the default and recommended option, you can explore other decentralized storage systems based on your needs and preferences.

  1. Events subscription:

In the Ethernity Cloud Runner integration, events play a crucial role in providing real-time feedback and updates during the execution of tasks. By subscribing to these events, developers can monitor the progress and completion status of their tasks.

Task Progress Event (ECEvent.TASK_PROGRESS):

The ECEvent.TASK_PROGRESS event is triggered when there is progress in the execution of a task. To capture and handle this event, developers can define a function, such as onTaskProgress, to process the event data. The event object, e, provides access to the event detail, which contains information about the task's current status.

In the example code provided:

const onTaskProgress = (e) => {
    if (e.detail.status === ECStatus.ERROR) {
        console.error(e.detail.message);
    } else {
        console.log(e.detail.message);
    }
};

runner.addEventListener(ECEvent.TASK_PROGRESS, onTaskProgress);

The onTaskProgress function receives the event object e, and it checks the e.detail.status to determine if the task encountered an error or if it is progressing successfully. If an error is detected, the function logs the error message to the console using console.error, otherwise, it logs the progress message using console.log.

Task Completed Event (ECEvent.TASK_COMPLETED):

The ECEvent.TASK_COMPLETED event is triggered when a task is successfully completed. Similar to the previous event, developers can define a function, such as onTaskCompleted, to handle the event and access the task result.

In the example code provided:

const onTaskCompleted = (e) => {
    console.log(`Task Result: ${e.detail.message.result}`);
}

runner.addEventListener(ECEvent.TASK_COMPLETED, onTaskCompleted);

The onTaskCompleted function receives the event object e, and it accesses the task result from e.detail.message.result. The function then logs the result to the console, providing developers with the outcome of the completed task.

By subscribing to these events, developers can stay informed about the execution progress and results of tasks, enabling them to monitor and respond to task executions effectively. The Ethernity Cloud Runner's event system enhances the developer experience, allowing for seamless integration and handling of task-related events in real-time.

  1. Task Execution:

await runner.run(ECRunner.PYNITHY_RUNNER_TESTNET, pythonCode);

The heart of the integration lies in the await runner.run(...) line, which initiates task execution through the Ethernity Cloud Runner. The runner.run(...) function accepts three arguments:

  • Runner Type: Specify the runner type, with currently two runners available for use on the TESTNET network:

    • Python runner: ECRunner.PYNITHY_RUNNER_TESTNET

    • Node.js runner: ECRunner.NODENITHY_RUNNER_TESTNET

  • Code: Provide the code to be executed as the task. For this example, it contains the Python code snippet to be executed (Ensure to preserve proper indentations).

  • Node Address (Optional): Include this argument if you wish to provide The Ethereum wallet address (node address) for processing the task. The Ethernity Cloud Runner offers two options for task approval:

    • Manual Approval: If you omit the node address, the task execution will be manually approved, allowing users to review the task details before execution proceeds.

    • Automatic Approval: If you choose to provide the node address, the task execution will be automatically approved, providing a seamless and quick execution process without manual intervention.

  1. Rendering the Button

return (
    <div className="container">
        <button className="centeredButton" onClick={executeTask}>Execute Task</button>
    </div>
);
  1. Final application code

import './App.css';
import EthernityCloudRunner from "@ethernity-cloud/runner";
import {ECEvent, ECRunner, ECStatus} from "@ethernity-cloud/runner/enums";

const code = `___etny_result___("Hello, World!")`;

// example of a Node.js script
// const jsCode = `function add(a, b) {\n  return a + b;\n}\n ___etny_result___(add(1, 10).toString());`;

function App() {
    const executeTask = async () => {
        const runner = new EthernityCloudRunner();
        // this is a server provided by Ethernity CLOUD, please bear in mind that you can use your own Decentralized Storage server
        const ipfsAddress = 'https://ipfs.ethernity.cloud:5001';
        runner.initializeStorage(ipfsAddress);

        const onTaskProgress = (e) => {
            if (e.detail.status === ECStatus.ERROR) {
                console.error(e.detail.message);
            } else {
                console.log(e.detail.message);
            }
        };

        const onTaskCompleted = (e) => {
            console.log(`Task Result: ${e.detail.message.result}`);
        }

        runner.addEventListener(ECEvent.TASK_PROGRESS, onTaskProgress);
        runner.addEventListener(ECEvent.TASK_COMPLETED, onTaskCompleted);


        // there are two types of runners: 
        //    - Python(ECRunner.PYNITHY_RUNNER_TESTNET) 
        //    - Node.js(ECRunner.NODENITHY_RUNNER_TESTNET)
        // based on this you should use appropriate runner type
        // for this example we are using PYNITHY_RUNNER_TESTNET since we are executing a python script
        await runner.run(ECRunner.PYNITHY_RUNNER_TESTNET, code);
        // in case you want to use Node.js
        //await runner.run(ECRunner.NODENITHY_RUNNER_TESTNET, code);
    };

    return (
        <div className="container">
            <button className="centeredButton" onClick={executeTask}>Execute Task</button>
        </div>
    );
}

export default App;
  1. Application styling

Now, navigate to the src/App.css file and proceed to enhance its content by adding the following CSS classes:

.container {
    /* Set the container to flex to align the button horizontally and vertically */
    display: flex;
    justify-content: center; /* Center horizontally */
    align-items: center; /* Center vertically */
    height: 100vh; /* Adjust the container's height based on your requirement */
}

.centeredButton {
    /* Add your button styles here */
    padding: 10px 20px;
    background-color: #007bff;
    color: #fff;
    border: none;
    cursor: pointer;
    font-size: 16px;
    border-radius: 5px;
}

In conclusion, the above-mentioned code elegantly integrates the Ethernity Cloud Runner into your React app, enabling seamless execution of Python/Node.js code snippets while facilitating interaction with the IPFS network for efficient data storage and retrieval. As a professional developer, you can now leverage this integration to enhance your React applications with powerful decentralized task execution capabilities.

Last updated