Skip to main content

Incorporate modules in the dapp

Let's put this into practice by moving code into smaller modules. Start by creating a folder named news_feed and adding a module.rell file inside it:

src/news_feed/module.rell
module;

Now, import everything from this module into your main.rell file by adding:

src/main.rell
import news_feed;

Next, create a file named src/news_feed/model.rell and move the entity definitions into this file.

src/news_feed/model.rell
entity user {
mutable name;
key id: byte_array;
key account;
}

entity follower {
index user;
index follower: user;
key user, follower;
}

entity post {
timestamp = op_context.last_block_time;
index user;
content: text;
}

Also, move the import statement for the account entity from the ft-library to the module.rell file. Adding it to the module.rell file makes sense as all files in the module can access it.

src/news_feed/module.rell
module;

import lib.ft4.accounts.{ account };
import lib.ft4.auth;

Similarly, move the auth_handler to src/news_feed/auth.rell and post_dto to src/news_feed/dto.rell. You can consider the require_user and format_user utility functions to add them directly to module.rell if you prefer. The queries are moved to src/news_feed/queries.rell, and the operations are moved to src/news_feed/operations.rell.

Your module.rell file in the news_feed module should now look like this:

src/news_feed/module.rell
module;

import lib.ft4.accounts.{ account };
import lib.ft4.auth;

function require_user(id: byte_array) = require(user @? { id }, "User with id %s does not exist".format(id));
function format_user(user) = "%s#%s".format(user.name, user.id.to_hex().sub(0, 5));

With proper imports, the main.rell file should now contain only the create_user operation, which is useful for testing purposes.

Now, create a new module called test_operations in the test folder by creating a file there and declaring it as a module:

src/test/test_operations.rell
module;

import lib.ft4.core.accounts.{ create_account_with_auth, single_sig_auth_descriptor };
import news_feed.*;

operation create_user(name, pubkey) {
val account = create_account_with_auth(single_sig_auth_descriptor(pubkey, set(["A", "T", "MySession"])));
create user ( name, pubkey, account );
}

In your test file, you'll need to import this module explicitly, possibly using relative imports:

src/test/news_feed_test.rell
import ^.test_operations.{ create_user };

The create_user operation is no longer accessible from main.rell, but it can still be helpful for testing against a test node. To support this, create a new module named development alongside main.rell, including the test operation:

src/development.rell
module;

import main;
import test.test_operations.*;

In your chromia.yml file, you can toggle between using the main module and the development module as the entry point for your dapp by altering the module: tag in the blockchains definition:

chromia.yml
blockchains:
my-news-feed:
module: development # set to "main" for production

You have now learned to use Rell modules to structure your project effectively. Your file structure should resemble the following:

├── development.rell
├── main.rell
├── news_feed
│ ├── auth.rell
│ ├── dto.rell
│ ├── model.rell
│ ├── module.rell
│ ├── operations.rell
│ └── queries.rell
└── test
├── news_feed_test.rell
└── test_operations.rell

In the next module, we will discuss a proper replacement for the create_user operation and how to integrate it with a front-end client.