Skip to content

Production ready Starter-kit for RUST based Web applications

Notifications You must be signed in to change notification settings

SystangoTechnologies/rustychain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


rustychain
Rust Web Starter-kit

Production ready Starter-kit for RUST based web applications.

RustyChain

RustyChain is a standalone blockchain ledger application that supports various transactions for managing fungible tokens. This README.md file provides documentation for the different transaction types and their associated parameters.

The main features supported in the current version of the application are as follows-

  • Transaction to Initialize Fungible Tokens: Users can create a transaction for initializing a new Fungible token using an API. They need to provide basic information such as token's name, symbol, decimals and initial supply in order to register the transaction.

  • Transaction to Mint Fungible Tokens: Any token initialized for the first time results in crediting the initial requested supply to the owner's wallet. Owner can now decide to either transfer these tokens to another user's address or simply mint new tokens to him/her. If new tokens are minted, then it will result in the increment of the total_supply of the token and new tokens will get credited to the recipient's address.

  • Transaction to Burn Fungible Tokens: The opposite of Mint is a Burn transaction. Burn results in reducing the balance of a user's wallet and the overall total supply of the token. Only an owner can burn tokens available in his wallet.

  • Transaction to Transfer Fungible Tokens: Users can transfer tokens from one wallet to another. If the target wallet doesn't yet exist, then it created first and then credited with the token balance. User can only transfer the amount of tokens which is available in their wallet, if a balance in excess is sent in the transaction then eventually at the time of transaction execution it will result in a failure.

  • Mine Blocks: Last, the application supports mining of blocks with a PoA arrangement. A selected miner gets rights to mine the blocks on ledger, currently a block gets created with at max 2 transactions and at the least 0 transactions too. This limit is configurable and can easily be updated.

Mining of a block results in execution of the transactions in raw state. After the execution is done, the transaction moves into either Success or Fail states.

  • Service Maintenance Scheduling: Quite overlooked yet an essential feature of a web application is administered ability to put service on maintenance. This feature allows admin to temporarily put the entire REST APIs on maintenance mode, during this period updates to the backend service can be performed without having to worry about serving client requests. Only an admin can put the service on hold and resume it via an API call.

The main aim behind creating this RUST application was to setup a boilerplate application showing how to use RUST for REST API use cases. We have used the following tools/crates while creating this codebase-

  • Actix - Server side framework
  • Diesel - ORM
  • r2d2 - Connection pool manager
  • PostgreSQL - SQL database
  • utoipa - Autogenerated OpenAPI documentation for Rust REST APIs
  • Docker - Containerizing framework
  • Swagger - API documentation
  • Redoc - API documentation
  • Rapidoc - API documentation

Onion Architecture

Onion architecture is a software design pattern that organizes the codebase into concentric layers, with the core layer containing the most fundamental and independent code, and the outer layers containing more specific and dependent code. This separation of concerns makes the codebase more maintainable and scalable, as each layer can be changed without affecting the other layers.

Actix web is a popular web framework for Rust that is well-suited for implementing the application layer of the onion architecture. It is built on top of the Actix actor framework, which provides a clear separation of concerns and modularity. Actix web is also high-performance and scalable, making it a good choice for building web applications of all sizes.

In simpler terms, onion architecture is a way of organizing your code so that it is easier to maintain and update. Actix web is a web framework that can be used to implement onion architecture in Rust.

Here is an analogy:

Imagine a cake with multiple layers. Each layer has a different flavor and texture, but they all work together to create a delicious cake. The onion architecture is similar to a cake in that each layer is independent of the other layers. This means that you can change the flavor or texture of one layer without affecting the other layers.

Actix web is like the frosting on the cake. It provides a layer of functionality that makes it easy to build web applications. However, Actix web is not necessary for onion architecture. You can use any web framework you want to implement onion architecture.

RustyChain Architecture Overview

The onion architecture is a layered architecture that is based on the onion model. Where each layer in the onion model is used to define the different layers of an application.

For this rust implementation 4 layers are used.

  • api (app) module: The outermost layer that contains the controllers and the endpoints definition, serialization and deserialization of the data, validation and error handling.
  • infrastructure: Layer that typically include database connections, external APIs calls, logging and configuration management.
  • services: Layer that contains the application's services, which encapsulate the core business logic and provide a higher-level abstraction for the application to interact with the domain entities.
  • domain: The innermost layer that contains the core business logic and entities of the application.

Folder structure:

.
├── migrations
├── scripts
│   └── run_postgres.sh # Run postgres in docker locally
├── src
│   ├── api
│   │   ├── controllers
│   │   │   └── ...  # controllers for the api
│   │   ├── dto # Data transfer objects  
│   │   │   └── ... # Individual DTOs
│   │   └── errors.py
│   ├── infrastructure
│   │   ├── services
│   │   │   └── ...  # Services that use third party libraries or services (e.g. email service)
│   │   ├── databases
│   │   │   └── ...  # Database adapaters and initialization
│   │   ├── repositories
│   │   │   └── ...  # Repositories for interacting with the databases
│   │   └── models
│   │       └── ...  # Database models
│   ├── domain
│   │   ├── mod.rs
│   │   ├── constants.rs
│   │   ├── errors.rs
│   │   ├── models
│   │   │   └── ...  # Business logic models traits or structs
│   │   ├── services
│   │   │   └── ...  # Service traits
│   │   └── repositories
│   │       └── ...  # Repository traits 
│   ├── services
│   │   └── ...  # Concrete service implementation for interacting with the domain (business logic)
│   ├── container.rs
│   ├── create_app.rs # app factory 
│   ├── lib.rs 
│   └── main.rs
  • migrations: Alembic's migration scripts are stored here.
  • scripts: contains the application's configuration settings.

Database Schema

The current schema looks as follows:

rustychain db schema

REST API Calls

Transactions

1. Initialize Fungible Token (InitFt)

Initialize a new fungible token.

Parameters:

  • from_address: Token owner's wallet address.
  • to_address: System contract address.
  • transaction_type: INIT_FT (TransactionType::InitFt).
  • value: Initial supply of tokens.
  • symbol: Token symbol.
  • name: Token name.
  • decimals: Token's allowed decimals.

Example Usage:

POST API Endpoint : http://localhost:8080/api/transactions

JSON Payload:

{
    "from_address": "0x00000000000000000000000000000000000ARPIT",
    "to_address": "0x00000000000000000000000000SYSTEMCONTRACT",
    "transaction_type": "INIT_FT",
    "value": 10000000000,
    "data": {
        "symbol": "APPL",
        "name": "Apple",
        "decimals": 0
    }
}

2. Mint Fungible Tokens (MintFt)

Mint fresh tokens of the initialized fungible token.

Parameters:

  • from_address: Token owner's wallet address.
  • to_address: Address to which tokens need to be minted.
  • transaction_type: MINT_FT (TransactionType::MintFt).
  • value: Number of tokens to be minted.
  • token_address: Address of the token to be minted, owned by the from_address.

Example Usage:

POST API Endpoint : http://localhost:8080/api/transactions

JSON Payload:

{
    "from_address": "0x00000000000000000000000000000000000ARPIT",
    "to_address": "0x742d35Cc6634C0532925a3b844Bc454e4430JOHN",    
    "transaction_type": "MINT_FT",
    "value": 200,
    "data": {
        "token_address": "0x8de21e962545c8622a9139387160405a8cee49f5"
    }
}

3. Burn Fungible Tokens (BurnFt)

Burn existing tokens in the fungible token contract.

Parameters:

  • from_address: Wallet address of the user who has tokens to burn.
  • to_address: NULL address (can be left empty or set to NULL).
  • transaction_type: BURN_FT (TransactionType::BurnFt).
  • value: Amount of tokens to be burnt (should be less than or equal to the from_address's balance).
  • token_address: Address of the token to be burned.

Example Usage:

POST API Endpoint : http://localhost:8080/api/transactions

JSON Payload:

{
  "from_address": "0xUserAddress",
  "to_address": "",
  "transaction_type": "BURN_FT",
  "value": 500,
  "data": {
        "token_address": "0x8de21e962545c8622a9139387160405a8cee49f5"
  }
}

4. Transfer Fungible Tokens (TransferFt)

Transfer owned tokens from one wallet address to another.

Parameters:

  • from_address: Sender's wallet address (user who has tokens).
  • to_address: Receiver's wallet address.
  • transaction_type: TRANSFER_FT (TransactionType::TransferFt).
  • value: Amount of tokens to be transferred (should be less than or equal to sender's balance).
  • token_address: Address of the token to be transferred.

Example Usage:

POST API Endpoint : http://localhost:8080/api/transactions

JSON Payload:

{
  "from_address": "0xSenderAddress",
  "to_address": "0xReceiverAddress",
  "transaction_type": "TRANSFER_FT",
  "value": 200,
  "data": {
        "token_address": "0x8de21e962545c8622a9139387160405a8cee49f5"
  }
}

5. Get All Transactions

Retrieve all transactions in paginated manner

Example Usage:

GET API Endpoint : http://localhost:8080/api/transactions

6. Get a Transaction by its Hash

Retrieve a transaction by its hash

Parameters:

  • txn_hash: Transaction Hash.

Example Usage:

GET API Endpoint : http://localhost:8080/api/transactions/{txn_hash}

Blocks

1. Mine a new Block

Creates a new block

Parameters:

  • miner_address: Miner's wallet address.

Example Usage:

POST API Endpoint : http://localhost:8080/api/blocks

JSON Payload:

{
  "miner_address": "string"
}

2. Get All Blocks

Retrieve all blocks in paginated manner

Example Usage:

GET API Endpoint : http://localhost:8080/api/blocks

3. Get a Block by its number

Retrieve a block in by its number

Parameters:

  • id: Block Number.

Example Usage:

GET API Endpoint : http://localhost:8080/api/blocks/{id}

Fungible Tokens

1. Get all Fungible Tokens

Retrieve all the fungible tokens in paginated manner

Example Usage:

GET API Endpoint : http://localhost:8080/api/fts

2. Get a Fungible Token by its address

Retrieve a fungible token by its hex address

Parameters:

  • token_address: Address of the Fungible Token.

Example Usage:

GET API Endpoint : http://localhost:8080/api/fts/{token_address}

Wallets

1. Get all Wallets

Retrieve all the wallets in paginated manner

Example Usage:

GET API Endpoint : http://localhost:8080/api/wallets

2. Get a Wallet by its Address and the associated Token's Address

Retrieve a wallet by its address and the associated token

Parameters:

  • wallet_address: Address of the User's Wallet.
  • token_address: Address of the Fungible Token.

Example Usage:

GET API Endpoint : http://localhost:8080/api/wallets/{wallet_address}/{token_address}

Service Context

1. Get Status

Retrieve the maintenance status of the backend

Example Usage:

GET API Endpoint : http://localhost:8080/admin/maintenance/status

2. Update Status

Update the maintenance status of the backend

Parameters:

  • maintenance: Set to true/false.

Example Usage:

POST API Endpoint : http://localhost:8080/admin/maintenance/status

JSON Payload:

{
  "maintenance": false
}

How to setup the application locally?

  1. Take a git pull on your local machine
  2. Ensure a postgreSQL instance is running locally/remotely
  3. Rename .env.sample to .env
  4. Set DATABASE_URL env variable in the .env file
  5. Set MAX_DB_SESSIONS_PER_WORKER to a realistic number (1/2/3 should be fine for local usage)
  6. Run 'diesel setup' command to setup the database
  7. Run 'diesel migration run' command to run all the migrations
  8. Run 'cargo watch -x run' to run with hot reloading enabled or simply 'cargo run'
  9. To try the integration tests, run 'sh scripts/test.sh'

Commands

Start local PG Instance

/usr/local/opt/postgresql@14/bin/postgres -D /usr/local/var/postgresql@14

Diesel migrations

Steps to perform migrations after checkout-

diesel setup
diesel migration generate <migration_name>
diesel migration run

Command to create a new migration script-

diesel migration generate <migration_name>

If you want to reset the database and rerun the migrations, use the following command-

diesel database reset

Launch server

Use the watch command if hot reloading is desired

cargo watch -x run
cargo run

Launch test cases

To launch the test cases with a clean database use the following command-

sh scripts/test.sh

Application URLs

Backend URL

http://localhost:8080/api

Swagger URL

http://localhost:8080/swagger-ui/

swagger ui

Redoc URL

http://localhost:8080/redoc

redoc

Rapidoc URL

http://localhost:8080/rapidoc

rapidoc

Contributors

Arpit Khandelwal

License

This project is licensed under the MIT License - see the LICENSE file for details.

References

About

Production ready Starter-kit for RUST based Web applications

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages