diff --git a/.github/workflows/test-contracts.yaml b/.github/workflows/test-contracts.yaml
index 96da315d6..f33bb7e87 100644
--- a/.github/workflows/test-contracts.yaml
+++ b/.github/workflows/test-contracts.yaml
@@ -9,151 +9,242 @@ on:
- "package*.json"
- "contracts/hardhat.config.ts"
- "contracts/tsconfig.json"
+ - "contracts/.solcover.js"
+ - ".github/workflows/test-contracts.yaml"
push:
branches:
- main
- paths:
- - "contracts/contracts/**"
- - "contracts/test/**"
- - "contracts/scripts/**"
- - "package*.json"
- - "contracts/hardhat.config.ts"
- - "contracts/tsconfig.json"
+
env:
- # Local (Right now using testnet)
LOCAL_PRIVATE_KEY_0: "0x105d050185ccb907fba04dd92d8de9e32c18305e097ab41dadda21489a211524"
LOCAL_PRIVATE_KEY_1: "0x2e1d968b041d84dd120a5860cee60cd83f9374ef527ca86996317ada3d0d03e7"
- LOCAL_PRIVATE_KEY_2: "0x45a5a7108a18dd5013cf2d5857a28144beadc9c70b3bdbd914e38df4e804b8d8"
- LOCAL_PRIVATE_KEY_3: "0x6e9d61a325be3f6675cf8b7676c70e4a004d2308e3e182370a41f5653d52c6bd"
- LOCAL_PRIVATE_KEY_4: "0x0b58b1bd44469ac9f813b5aeaf6213ddaea26720f0b2f133d08b6f234130a64f"
+ LOCAL_PRIVATE_KEY_2: "0x44162cd9b9a2f5582bd13b43cfd8be3bc20b8a81ee77f6bf77391598bcfbae4c"
LOCAL_JSON_RPC_ENDPOINT: "http://localhost:7546"
LOCAL_MIRROR_NODE_ENDPOINT: "http://localhost:5551"
- # Tesnet
- TESTNET_JSON_RPC_ENDPOINT: "https://296.rpc.thirdweb.com"
- TESTNET_MIRROR_NODE_ENDPOINT: "https://testnet.mirrornode.hedera.com"
permissions:
contents: read
-# ! It does NOT work if running locally using ACT (file sharing issue)
-
jobs:
- thread0:
+ # ==========================================================================
+ # Job 0: Build contracts (shared by test and coverage jobs)
+ # ==========================================================================
+ # Installs dependencies and builds contracts once, then caches both
+ # node_modules and build artifacts for downstream deployment jobs.
+ # Uses actions/cache (save) here and actions/cache/restore (read-only)
+ # in downstream jobs to avoid redundant npm ci + Solidity compilation.
+ # ==========================================================================
+ build:
+ name: Build Stablecoin Studio Contracts
runs-on: token-studio-linux-medium
- # ! Cannot use container with Hedera Local Network
- # container:
- # image: node:20.17.0-alpine3.20 # Using alpine for a smaller image
- permissions:
- contents: read
-
+ timeout-minutes: 10
steps:
- # * Initial steps
- name: Harden Runner
- uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e #v2.14.2
+ uses: step-security/harden-runner@v2
with:
egress-policy: audit
- - name: Checkout repository
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
+ - name: Checkout code
+ uses: actions/checkout@v4
- name: Setup Node.js
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0
+ uses: actions/setup-node@v4
with:
- node-version: "20.x"
+ node-version: "22"
+
+ - name: Install dependencies
+ run: npm ci
- - name: Initial steps
- uses: ./.github/actions/initial-steps
+ - name: Save dependencies to cache
+ uses: actions/cache/save@v4
with:
- module: "contracts"
- docker-engine-ubuntu: "true"
- # deps-create-env-file: "true" # Needed for testnet
+ path: |
+ node_modules
+ */node_modules
+ ~/.npm
+ key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}
- - name: Install and run Hedera Local Network
+ - name: Compile contracts
run: |
- npm install @hashgraph/hedera-local -g
- hedera start --detached
-
- # Needed for testnet
- # - name: Export ENV variables for contracts
- # uses: ./.github/actions/create-env-file
- # with:
- # api-access-token-1: ${{ secrets.API_ACCESS_TOKEN_1 }}
- # api-access-token-2: ${{ secrets.API_ACCESS_TOKEN_2 }}
- # module: "contracts"
-
- - name: Install and build Contracts
- uses: ./.github/actions/install-and-build
+ npm run build:contracts
+
+ - name: Save Hardhat artifacts
+ uses: actions/cache/save@v4
with:
- module: "contracts"
+ path: |
+ contracts/artifacts
+ contracts/cache
+ contracts/typechain-types
+ key: ${{ runner.os }}-contracts-build-${{ github.sha }}
+
+ # ==========================================================================
+ # Job 1: Execute smart contracts coverage (depends on test job)
+ # ==========================================================================
+ # Runs the smart contracts coverage in hardhat network.
+ # ==========================================================================
+ coverage:
+ name: Coverage of Stablecoin Studio Contracts
+ needs: [build]
+ runs-on: token-studio-linux-medium
+ timeout-minutes: 15
- # * Actual test command
- - name: Run
- run: npm run test:ci:thread0 --workspace=contracts -- --network local
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2
+ with:
+ egress-policy: audit
- - name: Stop Hedera Local Network
- if: always()
- run: hedera stop
+ - name: Checkout code
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - name: Clean project
- if: always()
- run: npm run clean --workspace=contracts
+ - name: Setup Node.js
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
+ with:
+ node-version: "22"
+ cache: npm
- thread1:
+ - name: Restore dependencies from cache
+ uses: actions/cache/restore@v4
+ with:
+ path: |
+ node_modules
+ */node_modules
+ ~/.npm
+ key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}
+ fail-on-cache-miss: true
+
+ - name: Restore build artifacts from cache
+ uses: actions/cache/restore@v4
+ with:
+ path: |
+ contracts/artifacts
+ contracts/typechain-types
+ contracts/cache
+ key: ${{ runner.os }}-contracts-build-${{ github.sha }}
+ fail-on-cache-miss: false
+
+ - name: Run coverage
+ run: |
+ npm run coverage:contracts
+
+ # ==========================================================================
+ # Job 2: Execute smart contracts tests (depends on build job)
+ # ==========================================================================
+ # Runs the smart contracts tests in hiero ledger Solo.
+ # ==========================================================================
+ tests:
+ name: Test Stablecoin Studio Contracts
+ needs: [build]
runs-on: token-studio-linux-medium
- # ! Cannot use container with Hedera Local Network
- # container:
- # image: node:20.17.0-alpine3.20 # Using alpine for a smaller image
- permissions:
- contents: read
+ timeout-minutes: 60
steps:
- # * Initial steps
- name: Harden Runner
- uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e #v2.14.2
+ uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2
with:
egress-policy: audit
- - name: Checkout repository
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
+ - name: Checkout code
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0
- with:
- node-version: "20.x"
-
- - name: Initial steps
- uses: ./.github/actions/initial-steps
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
- module: "contracts"
- deps-contracts-install: "true"
- # deps-create-env-file: "true" # Needed for testnet
+ node-version: "22"
+ cache: npm
- - name: Install and run Hedera Local Network
+ - name: Check Docker availability
+ id: docker-check
run: |
- npm install @hashgraph/hedera-local -g
- hedera start --detached
-
- # Needed for testnet
- # - name: Export ENV variables for contracts
- # uses: ./.github/actions/create-env-file
- # with:
- # api-access-token-1: ${{ secrets.API_ACCESS_TOKEN_1 }}
- # api-access-token-2: ${{ secrets.API_ACCESS_TOKEN_2 }}
- # module: "contracts"
-
- - name: Install and build Contracts
- uses: ./.github/actions/install-and-build
+ if docker info > /dev/null 2>&1; then
+ echo "available=true" >> "${GITHUB_OUTPUT}"
+ echo "Docker is available"
+ docker --version
+ else
+ echo "available=false" >> "${GITHUB_OUTPUT}"
+ echo "::warning::Docker not available - skipping Solo deployment test"
+ fi
+
+ - name: Restore dependencies from cache
+ uses: actions/cache/restore@v4
with:
- module: "contracts"
-
- # * Actual test command
- - name: Run
- run: npm run test:ci:thread1 --workspace=contracts -- --network local
-
- - name: Stop Hedera Local Network
- if: always()
- run: hedera stop
+ path: |
+ node_modules
+ */node_modules
+ ~/.npm
+ key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}
+ fail-on-cache-miss: true
+
+ - name: Restore build artifacts from cache
+ uses: actions/cache/restore@v4
+ with:
+ path: |
+ contracts/artifacts
+ contracts/typechain-types
+ contracts/cache
+ key: ${{ runner.os }}-contracts-build-${{ github.sha }}
+ fail-on-cache-miss: false
+
+ - name: Setup Hiero Solo Network
+ id: solo
+ if: steps.docker-check.outputs.available == 'true'
+ uses: hiero-ledger/hiero-solo-action@fbca3e7a99ce9aa8a250563a81187abe115e0dad # v0.16.0
+ with:
+ installRelay: true
+ installMirrorNode: true
+ hbarAmount: 10000000
+
+ - name: Create ECDSA account 0
+ if: steps.solo.outcome == 'success'
+ env:
+ DEPLOYMENT: ${{ steps.solo.outputs.deployment }}
+ KEY: ${{ env.LOCAL_PRIVATE_KEY_0 }}
+ run: |
+ DER_KEY=${KEY#0x}
+
+ solo ledger account create \
+ --ecdsa-private-key "$DER_KEY" \
+ --set-alias \
+ --hbar-amount 10000000 \
+ --deployment "$DEPLOYMENT" \
+ --dev
+
+ - name: Create ECDSA account 1
+ if: steps.solo.outcome == 'success'
+ env:
+ DEPLOYMENT: ${{ steps.solo.outputs.deployment }}
+ KEY: ${{ env.LOCAL_PRIVATE_KEY_1 }}
+ run: |
+ DER_KEY=${KEY#0x}
+
+ solo ledger account create \
+ --ecdsa-private-key "$DER_KEY" \
+ --set-alias \
+ --hbar-amount 10000000 \
+ --deployment "$DEPLOYMENT" \
+ --dev
+
+ - name: Create ED25519 account
+ if: steps.solo.outcome == 'success'
+ env:
+ DEPLOYMENT: ${{ steps.solo.outputs.deployment }}
+ KEY: ${{ env.LOCAL_PRIVATE_KEY_2 }}
+ run: |
+ DER_KEY=${KEY#0x}
+
+ solo ledger account create \
+ --ed25519-private-key "$DER_KEY" \
+ --hbar-amount 10000000 \
+ --deployment "$DEPLOYMENT" \
+ --dev
+
+ - name: Run tests
+ if: steps.docker-check.outputs.available == 'true' && steps.solo.outcome == 'success'
+ run: |
+ npm run test --workspace=contracts -- --network local
- - name: Clean project
- if: always()
- run: npm run clean --workspace=contracts
+ - name: Stop Hiero Solo Network
+ if: always() && steps.docker-check.outputs.available == 'true'
+ run: |
+ docker stop $(docker ps -q --filter "name=hiero") || true
+ docker rm $(docker ps -aq --filter "name=hiero") || true
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 78572d7f9..33a608f4a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,8 @@ coverage/
# History
.history/
+
+# Gas report
+gas-report.txt
+
+.tasks
diff --git a/README.md b/README.md
index 9a6a7345c..7bebc9e31 100644
--- a/README.md
+++ b/README.md
@@ -6,357 +6,301 @@
-### Table of Contents
+## Introduction
-- **[Abstract](#abstract)**
-- **[Context](#context)**
-- **[Objective](#objective)**
-- **[Overview](#overview)**
- - [What is a stablecoin](#what-is-a-stablecoin)
- - [Creating stablecoins](#creating-stablecoins)
- - [Managing stablecoins](#managing-stablecoins)
- - [Operating stablecoins](#operating-stablecoins)
- - [Stablecoin categories](#stablecoins-categories)
- - [Proof of reserve](#proof-of-reserve)
- - [Multisignature functionality](#multisignature-functionality)
-- **[Architecture](#architecture)**
-- **[Technologies](#technologies)**
-- **[Installation](#installation)**
-- **[Build](#build)**
-- **[Recommendations](#recommendations)**
-- **[Testnet reset procedure](#testnet-reset-procedure)**
-- **[Deploying the stablecoin factories](#deploying-the-stablecoin-factories)**
-- **[v1 to v2 Migration](#v1-to-v2-migration)**
-- **[v2 to v3 Migration](#v2-to-v3-migration)**
-- **[v3 to v4 Migration](#v3-to-v4-migration)**
-- **[Development manifesto](#development-manifesto)**
-- **[Support](#support)**
-- **[Contributing](#contributing)**
-- **[Code of conduct](#code-of-conduct)**
-- **[License](#license)**
+**Stablecoin Studio** is an institutional-grade framework to issue and manage stablecoins on the **Hedera network**. It leverages the **Hedera Token Service (HTS)** for speed and **Smart Contracts** for programmable compliance.
-# Abstract
+The toolkit provides everything needed to create, configure, and operate stablecoins with enterprise-level features including multi-role access control, KYC/AML compliance, proof of reserve integration, and multisignature transaction support.
-The Stablecoin Studio is a comprehensive set of tools and resources designed to enable developers to build applications and services that make use of the stablecoin. The accelerator includes smart contracts, documentation, and sample code to help developers understand how to use the accelerator and other functionality provided by the platform. With the Stablecoin Studio, developers can easily integrate the stablecoin into their own applications or create new applications or services that make use of the stablecoin's unique features. Whether you're a seasoned cryptocurrency developer or new to the space, the Stablecoin Studio has everything you need to start building with stablecoins today.
+This monorepo is structured with **npm workspaces** and is designed for scalability, modularity, and enterprise adoption.
-# Context
+---
-As people are looking to adopt cryptocurrencies, they sometimes have their reservations about potential price volatility. This is especially true when it comes to paying for goods and services.
+## Key Features
-That is where stablecoin comes in. Unlike other cryptocurrencies, stablecoin are usually pegged to another currency. This means that the value of a stablecoin will follow the value of that currency. Take for instance some of the most popular stablecoin like Tether (USDT), USD Coin (USDC) and Binance USD (BUSD), which are all pegged to the US Dollar.
+- **Stablecoin Management**
+ - Stablecoins as **decorator tokens** on top of standard Hedera Tokens.
+ - **Diamond proxy pattern** with centralized resolver for upgradeable smart contracts.
+ - Fine-grained **Role-Based Access Control** (Admin, Cash-in, Burn, Wipe, Pause, Freeze, KYC, Rescue, Delete).
+ - Split supply roles with cash-in/burn separation and configurable supply allowances.
-There are also some crypto backed stablecoin such as DAI by MakerDAO, or commodity backed stablecoin such as Paxos Gold (PAXG) by Paxos.
+- **Compliance & Security**
+ - Native **KYC/AML** support with per-account verification.
+ - Account **freezing** and **wiping** for regulatory compliance.
+ - **Proof of Reserve** integration via Chainlink AggregatorV3Interface.
+ - Rescue capabilities for asset recovery.
-Stablecoin have transformed the way crypto markets work by allowing traders to exchange their volatile crypto assets for a stable asset that can quickly be transferred to any other platform. If they can change the way people trade, they can also become a real breakthrough in e-commerce.
+- **Multisignature Support**
+ - Backend API for managing multisig transaction workflows.
+ - Support for Hedera `keyList` and `thresholdKey` accounts.
+ - Temporary transaction storage with signature collection.
-# Objective
+- **Enterprise Development Practices**
+ - **Domain-Driven Design (DDD)** and **Hexagonal Architecture**.
+ - **Command Query Separation (CQS)** pattern in the SDK.
+ - Dependency injection with tsyringe.
+ - Wallet adapter support (HashPack, MetaMask, Blade, Custodial).
-A stablecoin is a type of cryptocurrency that is designed to maintain a stable value relative to a specific asset or basket of assets. Currently, there is no out-of-the-box solution to create and manage stablecoins on Hedera Hashgraph. This project aims to provide developers with the tools they need to build applications that make use of the stablecoin, such as wallets, as well as documentation and sample code to help developers understand how to use the SDK and other functionality provided by the stablecoin platform. With all of this, we want to enable developers to integrate the stablecoin into their own applications or systems.
+## Monorepo Structure
-# Overview
-
-This solution consists of a set of tools, including Smart Contracts, SDK, CLI and UI to facilitate the deployment and management of stablecoins in Hedera Hashgraph.
-
-## What is a stablecoin
-
-A stablecoin is a **decorator** to a standard Hedera Token.
-Each stablecoin maps to an _underlying_ Hedera Token and adds the following functionality:
-
-- **Multiple roles**
-
- Hedera Tokens' operations (Wipe, Pause, ...) can only be performed by the accounts to which they are assigned (WipeKey, PauseKey, ...).
-
- Stablecoins allow for multiple accounts to share the same operation rights, we can wipe/pause/... tokens using any of the accounts with the wipe/pause/... role respectively.
-
-- **Supply role split into Cash-in and Burn roles**
-
- The Hedera Tokens' supply account has the right to change the supply of the token, it can be used to mint and burn tokens.
-
- Stablecoins split the supply role in two, the *cash-in* and the *burn* roles which can be assigned to different accounts.
-
-- **Cash-in role**
-
- When Hedera Tokens are minted, they are automatically assigned to the treasury account. If we want to assign them to another account, a second transaction (signed by the treasury account) is required to transfer the tokens.
-
- Stablecoins implement a "cash-in" operation that allows cash-in role owners to mint and assign tokens to any account in a single transaction.
- The cash-in role comes in two flavours:
-
- - _unlimited_: Accounts with the unlimited cash-in role can mint as many tokens as they wish (as long as the total supply does not exceed the max supply).
- - _limited_: Accounts with the limited cash-in role can only mint a limited number of tokens. The maximum cash-in amount is defined for each account individually and can be increased/decreased at any time by the admin account.
-
-- **Rescue role**
-
- When the treasury account for a stablecoin's underlying token is the main stablecoin smart contract itself, any token assigned to the treasury account can be managed by accounts having the _rescue_ role.
- It is important to note that the initial supply of tokens (minted when the Hedera token was created) is always assigned to the treasury account, which means that rescue role accounts will be required to transfer those tokens to other accounts.
-
- In the same way, smart contract HBAR can also be managed by accounts having the _rescue_ role. Therefore, _rescue_ role accounts will be able to manage both the tokens and the HBAR of the smart contract.
-
-> The account deploying the stablecoin can be set as the administrator of the underlying token (instead of the smart contract itself), in which case, that account could completely bypass the stablecoin and interact with the underlying token directly in order to change the keys associated to the roles. This would completely decouple the stablecoin from the underlying token making the above-mentioned functionalities impossible.
-
-## Creating stablecoins
-
-Every time a stablecoin is created, a new Hedera Token is created (the underlying token) and the following smart contracts are deployed:
-
-- The stablecoin proxy smart contract: pointing to the `HederaTokenManager` logic smart contract that was passed as an input argument(\*). Proxies are used to make stablecoins upgradable.
-- The stablecoin proxy admin smart contract: this contract will act as an intermediary to upgrade the stablecoin proxy implementation. For more information on this, check the [contract module's README](https://github.com/hashgraph/stablecoin-studio/tree/main/contracts/README.md).
-
-An smart contract, named `StablecoinFactory`, must be previously deployed since implements the flow to create a new stablecoin in a single transaction. A default `StablecoinFactory` is deployed, but any user will be able to [deploy their own factory](#deploying-the-stablecoin-factories).
-
-(\*)By default, the HederaTokenManager smart contract that will be used will be the pre-deployed one, but users can use any other contract they want. For more information on this check the contract module's README.
-
-Users interact with the stablecoin proxy smart contract, instead of doing with the stablecoin logic smart contract, because its address will never change. stablecoin logic smart contract address change if a new version is deployed.
-
-> It is important to note that when creating a new stablecoin, the user will have the possibility to specify the underlying token's keys (those that will have the wipe, supply, ... roles attached). By default, those keys will be assigned to the _stablecoin proxy smart contract_ because, by doing that, the user will be able to enjoy the whole functionality implemented in this project through the stablecoin logic smart contract methods. **NEVERTHELESS**, the user is free to assign any key to the public key of any account (not only during the creation process but also later, if the user's account was set as the underlying key admin), except the admin key and the supply key, that will always be automatically assigned to the stablecoin proxy smart contract. If the user assigns a key to the public key of a different account, the stablecoin proxy smart contract will not be able to fully manage the underlying token, limiting the functionality it exposes to the user. These keys could be even not assigned, so the related functionalities couldn't be performed. It is also worth noting that just like the user will have the possibility to assign any key to the public key of any account other than the stablecoin smart contract proxy, he/she will be able to assign it back too.
-
-## Managing stablecoins
-
-Every time a stablecoin is deployed, the deploying account will be defined as the stablecoin administrator and will be granted all roles (wipe, rescue, ...). That account will have the possibility to assign and remove any role to any account, increase and decrease cash-in limits, etc...
-
-## Operating stablecoins
-
-Any account having any role granted for a stablecoin can operate with it accordingly. For instance, if an account has the burn role granted, it will be allowed to burn tokens. Accounts do not need to be associate with the underlying token in order to operate with it, they only need to be granted roles. On the other hand, if they want to own tokens, they will have to associate the token as for any other Hedera token.
-
-## Stablecoins categories
-
-From an account's perspective, there are two kinds of stablecoins:
-
-- _Internal stablecoins_
-
-Every stablecoin created using the account, independently of the roles the account might have.
-
-- _Imported stablecoins_
-
-Every stablecoin for which the account has at least one role but was created using a different account.
-
-## Proof of reserve
-
-Under the current implementation, all stablecoins may choose to implement a proof of reserve data feed at creation (new reserve data feeds can only be deployed when a stablecoin has been created as part of the creation process itself. They can not be deployed independently).
-
-> A proof of reserve is, in very simple terms, an external feed that provides the backing of the tokens in real world. This may be FIAT or other assets.
-
-### Setting up a proof of reserve
-
-During setup, it is possible to link an existing data feed by providing the smart contract's address, or create a new one based on our implementation. If a reserve was created during the stablecoin deployment, it will also be possible to edit the amount of the reserve.
-
-> The initial supply of the stablecoin cannot be higher than the reserve initial / current amount.
-
-The interface the reserve data feed must implement for the stablecoin to be able to interact with is the **AggregatorV3Interface** defined and used by Chainlink for its [Data Feeds](https://docs.chain.link/data-feeds/). This means that any reserve data feed implemented by Chainlink or adhering to Chainlink's standards is fully compatible with our stablecoins.
-
-Therefore, three options exist
-
-- **stablecoin not linked to a reserve:** No known reserve collateralizing the Token. stablecoins with no reserve are technically not "stable" but just "coins".
-- **stablecoin linked to a reserve but no data feed is provided:** This will deploy and initialize a reserve based on our example implementation. This reserve is meant to be used for demo purposes and allows the admin to change the reserve amount to showcase the integration between both.
-- **stablecoin linked to a reserve and an existing data feed is provided**: This data feed will be used to check the reserve before minting any new tokens.
-
-In any case, the reserve address can be edited after creation. However, changing the amount in the reserve can only be performed when the reserve smart contract was deployed during the stablecoin creation.
-
-For more information about the SDK and the methods to perform these operations, visit to the [docs](https://github.com/hashgraph/stablecoin-studio/tree/main/sdk#reserve-data-feed).
-
-## Multisignature functionality
-
-Hedera allows for the creation of accounts with complex key structures (__multi-key accounts__), enabling configurations that require multiple signatures from different ED25519 or ECDSA keys to authorize transactions.
-
-These accounts can use simple multi-signature setups or more sophisticated threshold key arrangements, where a specific number of approvals from a designated group of key holders is necessary to execute transactions. This functionality is ideal for enhancing security and governance in applications requiring collective decision-making.
+```
+├── contracts/ # Solidity smart contracts (Hardhat)
+│ ├── contracts/
+│ │ ├── extensions/ # Facets (Burn, CashIn, Freeze, KYC, Pause, Rescue, Reserve, Roles, Wipe, Hold)
+│ │ ├── resolver/ # BusinessLogicResolver and ResolverProxy
+│ │ └── Interfaces/ # Contract interfaces
+│ └── test/
+├── sdk/ # TypeScript SDK (Hexagonal Architecture + DDD + CQS)
+│ └── src/
+│ ├── domain/ # Domain entities and business logic
+│ ├── app/ # Application layer (commands, queries, handlers)
+│ ├── port/ # Inbound/outbound ports
+│ └── core/ # Infrastructure and cross-cutting concerns
+├── backend/ # NestJS REST API for multisignature transactions
+├── cli/ # Command-line interface for stablecoin operations
+├── web/ # React DApp for stablecoin management
+├── docs/ # Documentation site (Docusaurus)
+├── documentation/ # Technical documentation content
+│ ├── gettingStarted/ # Setup and onboarding guides
+│ ├── sdk/ # SDK documentation
+│ ├── backend/ # Backend documentation
+│ ├── client/ # CLI documentation
+│ └── web/ # Web DApp documentation
+└── package.json # Workspace configuration and root scripts
+```
-For more information about this type of account please check the official Hedera documentation about [key structures](https://docs.hedera.com/hedera/core-concepts/keys-and-signatures#key-structures).
+## Documentation
-> If you need to deploy a brand new multikey account you can use our [script](https://github.com/hashgraph/stablecoin-studio/tree/main/sdk/scripts/CreateMultisigAccount.ts). Follow the instructions in the script itself (comment section at the begining)
+**Complete documentation:** [documentation/intro.md](documentation/intro.md)
-The Stablecoin solution enables the management of a stablecoin through multi-key accounts.
+This project follows a **"Docs-as-Code"** philosophy with comprehensive documentation maintained alongside the source code.
-When an operation (cash-in, burn, ...) is carried out using the _multisig_ mode, the corresponding transaction will not be directly submitted to the Hedera DLT, instead, it will be temporarily stored in a backend waiting for the multisig account key owners to sign it. Once it has been signed by all the required keys it will be available for submission.
+You can also run the documentation site locally:
-It's crucial to note that there is a time constraint for multisig transactions: they must be signed and submitted within three minutes of their initiation. If this timeframe is not met, the Hedera DLT will consider these transactions as expired and reject them.
+```bash
+npm run docs
+```
-> The functionality has a limitation: Complex keys must have only one level, in other words, key list and threshold keys must contain only ED25519/ECDSA keys, they cannot contain firther key lists and/or threshold keys.
+## Architecture
+
+### High-Level Overview
+
+```mermaid
+flowchart TD
+ subgraph Users
+ U1[Token Holder]
+ U2[Issuer / Admin]
+ U3[Operator]
+ end
+
+ subgraph CLI
+ C[CLI Application]
+ end
+
+ subgraph Web
+ W[React DApp]
+ end
+
+ subgraph SDK
+ S[TypeScript SDK]
+ end
+
+ subgraph Backend
+ B[NestJS API - Multisig]
+ end
+
+ subgraph SmartContracts
+ F[StableCoinFactory]
+ R[BusinessLogicResolver]
+ P[ResolverProxy - Diamond]
+ FC[Facets - Burn CashIn Freeze KYC Pause Rescue Reserve Roles Wipe]
+ end
+
+ subgraph Hedera
+ H1[(Mirror Node)]
+ H2[(RPC Node)]
+ HTS[Hedera Token Service]
+ end
+
+ U1 <--> W
+ U2 <--> W
+ U3 <--> C
+
+ W <--> S
+ C <--> S
+ S <--> B
+ S <--> F
+
+ F --> R
+ R --> P
+ P --> FC
+
+ FC <--> HTS
+ S <--> H1
+ S <--> H2
+```
-### Steps to deploy a multisig-managed stablecoin
+## Installation & Setup
-If you wish to deploy a stablecoin and fully manage it with a multisig account the steps to follow are:
-- Using a single key account, deploy a stablecoin assigning all roles and the proxy admin ownership to the multisig account
-- Once the stablecoin is deployed, assign the "admin" role to the multisig account.
-> The admin role is the only one that cannot be assigned automatically during the initial deployment
-- Remove the admin role from the single key account used to deploy the stablecoin
-> The admin role is automatically assigned to the deploying account
-- Connect to the stablecoin platform using the multisig account and manually import the deployed stablecoin
-> Since the deployment was carried out by another account, the multisig account was not associated to the token, that is the reason why you need to import it manually. It you associate your multisig account to the stablecoin's hedera token, you will not need to import it anymore.
+### Prerequisites
+- **Node.js**: v18.16.0 or higher (LTS recommended)
+- **npm**: v10 or higher
-# Architecture
+### Quick Setup
-The project is divided in 5 node modules:
+From the monorepo root:
+```bash
+npm run setup
```
- /contracts
- /backend
- /sdk
- /cli
- /web
-```
-
-- **`/contracts`:** The solidity smart contracts implementing the stablecoin functionalities.
-- **`/backend`:** A Backend tool implemented for managing the multisignature transactions that must be signed then submitted to the Hdera DLT. It exposes a REST API.
-- **`/sdk`:** The SDK implementing the features to create, manage and operate stablecoins. The SDK interacts with the smart contracts and the backend REST API and exposes an API to be used by client facing applications.
-- **`/cli`:** A CLI tool for creating, managing and operating stablecoins. Uses the SDK exposed API.
-- **`/web`:** A DApp developed with React to create, manage and operate stablecoins. Uses the SDK exposed API.
+This command installs all dependencies and builds all modules in the correct order (contracts → SDK → CLI, Web, Backend).
-Learn more about them in their README:
+### Selective Setup
-- [contracts](https://github.com/hashgraph/stablecoin-studio/tree/main/contracts/README.md)
-- [backend](https://github.com/hashgraph/stablecoin-studio/tree/main/backend/README.md)
-- [sdk](https://github.com/hashgraph/stablecoin-studio/tree/main/sdk/README.md)
-- [cli](https://github.com/hashgraph/stablecoin-studio/tree/main/cli/README.md)
-- [web](https://github.com/hashgraph/stablecoin-studio/tree/main/web/README.md)
+You can install and build specific modules:
-# Technologies
+```bash
+# Install specific module dependencies
+npm run install:contracts
+npm run install:sdk
+npm run install:cli
+npm run install:web
+npm run install:backend
+npm run install:docs
+```
-- **Smart contracts**: Solidity version 0.8.16 (and lower versions for contracts imported from external sources like OpenZeppelin).
-- **SDK, Backend, CLI and UI**: Typescript `>=4.7`
-- **SDK**: Node `>= v18.13`
-- **UI**: React.js `>=2.2.6`
-- **CONTRACTS**: Hardhat `^2.14.0`
+### Build Order
-# Installation
+Modules have dependencies on each other. Build order matters:
-In a terminal:
+1. **Contracts** must be built first (compiles Solidity, generates ABIs)
+2. **SDK** depends on contracts
+3. **CLI** and **Web** depend on SDK
+4. **Backend** can be built independently
-```
-npm run install:all
+```bash
+npm run build:contracts # 1st
+npm run build:sdk # 2nd
+npm run build:cli # 3rd
+npm run build:web # or 3rd
+npm run build:backend # Independent
```
-This will install the dependencies in all projects and sets up the links between them.
+### Environment Configuration
-You can now start developing in any of the modules.
+Each module has its own `.env` configuration. Sample files are provided:
-> To individual installation or running SDK/CLI/UI you can find all the information in their respective readme cited above.
+- **Contracts**: `contracts/.env` (test account credentials) — use `contracts/.env.sample`
+- **CLI**: `cli/hsca-config.yaml` — use `cli/hsca-config.sample.yaml`
+- **Web**: `web/.env` (factory addresses, mirror node, RPC endpoints)
+- **Backend**: `backend/.env` (database, port configuration)
-# Build
+## Development Workflows
-When making modifications to any of the modules, you have to re-compile the dependencies, in this order, depending on which ones the modifications where made:
+### Smart Contracts
```bash
- // 1st
- $ npm run build:contracts
- // 2nd
- $ npm run build:sdk
- // 3rd
- $ npm run build:cli
- // or
- $ npm run build:web
+cd contracts
+npm run compile # Compile changed contracts
+npm run compile:force # Force recompile all
+npm test # Run all tests
+npm run test:parallel # Run tests in parallel
```
-Or within any of the modules:
+### SDK
```bash
- $ cd [module] // sdk, web, contracts, etc
- $ npm run build
+cd sdk
+npm run build # Build SDK
+npm test # Run tests
+npm run test:watch # Watch mode
```
-# Recommendations
-
-If you are using VSCode we recommend the use of the solidity extension from nomicFoundation, it will facilitate the use of hardhat.
-[hardhat-vscode](https://github.com/NomicFoundation/hardhat-vscode)
-
-> This may not be compatible with others solidity extensions, such as this one. [vscode-solidity](https://github.com/juanfranblanco/vscode-solidity)
-
-# Deploying the stablecoin factories
-In order to be able to deploy any stablecoin, the `HederaTokenManager` and `StablecoinFactory` smart contracts must be deployed on the network. Whenever a new version of these contracts is needed or when the testnet is reset, new contracts must be deployed. Moreover, the address of the `StablecoinFactory` smart contract must be updated in the SDK, CLI and web modules as explained above.
-
-We provide default addresses for the factory and the business logic resolver that we have deployed for anyone to use that are updated whenever a new version is released.
+### CLI
-You can find them associated to each version in [FACTORY_VERSION.md](./FACTORY_VERSION.md) and [RESOLVER_VERSION.md](./RESOLVER_VERSION.md)
-
-Follow the steps in the [contracts docs](https://github.com/hashgraph/stablecoin-studio/tree/main/contracts#deploy-factory) to learn how to deploy the factories.
-
-# V1 to V2 Migration
-V2 smart contracts are not compatible with V1.
-
-If you have deployed Stablecoins in V1 and want to migrate them to V2 please follow the procedure described in the `contracts/README`document `V1 to V2 migration` section.
-
-# V2 to V3 Migration
-V3 BLR smart contracts are not compatible with V2.
-
-If you have deployed Stablecoins that refer to a BLR V2 and want them to start refering to a BLR V3 please follow the procedure described in the `contracts/README`document `V2 to V3 migration` section.
-
-# V3 to V4 Migration
-Existing v3 StableCoins can be updated to v4 with no migration procedure, only bug fixes have been added to the stablecoin code.
-
-However the StableCoin factory deployment method has a new parameter `updatedAtThreshold` that makes previous backends or smart contracts interacting with it incompatible.
-
-# Testnet reset procedure
-
-Whenever a testnet reset occurs, the factories must be re-deployed and the addresses on the SDK must be updated.
-
-1. Follow the steps in [Deploying the stablecoin factories](#deploying-the-stablecoin-factories) to deploy the factories.
-2. Update the addresses in SDK's `.env` file to the newly deployed factories in order to pass the SDK's tests.
-3. Update the addresses in the CLI's configuration file in order to use the new factories in the CLI.
-4. Update the addresses in the web's `.env` file in order to use the new factories in the DApp.
-5. Create a PR to be validated and merged for the new version.
-
-# Fees
-All fees are subject to change. The fees below reflect a base price for the transaction or query. Transaction characteristics may increase the price from the base price shown below. The following table reflects the cost that the transaction have through the Smart Contracts.
+```bash
+cd cli
+npm run build # Build CLI
+npm start # Start CLI
+npm run start:wizard # Start in wizard mode
+```
-| Operation | Dollar | Gas |
-|----------------|--------------|------------|
-| Cash in | 0.01$ | 101.497 |
-| Burn | 0.005$ | 60.356 |
-| Wipe | 0.005$ | 60.692 |
-| Freeze | 0.005$ | 56.261 |
-| Unfreeze | 0.005$ | 56.262 |
-| Grant KyC | 0.005$ | 56.167 |
-| Revoke KyC | 0.005$ | 56.195 |
+### Web DApp
-# JSON-RPC Relays
-Anyone in the community can set up their own JSON RPC relay that applications can use to deploy, query, and execute smart contracts. You can use your local RPC-relay following this [instructions](https://github.com/hashgraph/hedera-json-rpc-relay) or you can use one of the community-hosted Hedera JSON RPC relays like:
-- [Hashio](https://swirldslabs.com/hashio/)
-- [Arkhia](https://www.arkhia.io/features/#api-services)
-- [ValidationCloud](https://docs.validationcloud.io/v1/hedera/json-rpc-relay-api)
+```bash
+cd web
+npm run build # Build web app
+npm start # Start dev server on http://localhost:3000
+```
-# Development manifesto
+### Backend
-The development of the project follows enterprise-grade practices for software development. Using DDD, hexagonal architecture, and the CQS pattern, all within an agile methodology.
+```bash
+cd backend
+npm run build # Build backend
+npm run start:dev # Development mode with watch
+npm run start:debug # Debug mode
+npm test # Unit tests
+npm run test:e2e # End-to-end tests
+```
-## Domain driven design
+## Testing
-By using DDD (Domain-Driven Design), we aim to create a shared language among all members of the project team, which allows us to focus our development efforts on thoroughly understanding the processes and rules of the domain. This helps to bring benefits such as increased efficiency and improved communication.
+Run tests for individual modules:
-## Hexagonal architecture
+```bash
+npm test --workspace=contracts # Smart contract tests
+npm test --workspace=sdk # SDK tests
+npm test --workspace=backend # Backend unit tests
+```
-We employ this architectural pattern to differentiate between the internal and external parts of our software. By encapsulating logic in different layers of the application, we are able to separate concerns and promote a higher level of isolation, testability, and control over business-specific code. This structure allows each layer of the application to have clear responsibilities and requirements, which helps to improve the overall quality and maintainability of the software.
+### Code Quality Standards
-## CQS and command handlers
+- **SDK / CLI / Web**: >70% code coverage
+- **Smart Contracts**: 100% coverage of public/external methods
+- All code must pass prettier and linting checks
-We use a separation of queries/commands, query handlers/command handlers to divide state changes from state reads, with the goal of decoupling functional workflows and separating view models from the domain. By using command handlers and an internal command bus, we are able to completely decouple the use cases within the system, improving flexibility and maintainability. This has been achieved by developing a fully typed TS Command / Query Handler module.
+```bash
+npm run prettier # Format all modules
+npm run prettier:check # Check formatting without changes
+```
-## Code standards
+## Continuous Integration
-The SDK,CLI and UI have over 70% code coverage in unit and integration tests. The Smart Contracts have a 100% code coverage(\*).
+The project uses separate GitHub Actions workflows for each module:
-_(\*) we could not find any tool to automatically measure the Smart Contracts coverage, but we included tests for all external and public methods implemented by this project (external and public methods imported from trusted external sources were not considered)._
+- **Contracts Tests** (`.github/workflows/test-contracts.yaml`): Runs when contract files change
+- **SDK Tests** (`.github/workflows/test-sdk.yaml`): Runs when SDK files change
+- **Backend Tests** (`.github/workflows/test-backend.yaml`): Runs when backend files change
+- **CLI Tests** (`.github/workflows/test-cli.yaml`): Runs when CLI files change
+- **Web Tests** (`.github/workflows/test-web.yaml`): Runs when web files change
+- **Publish** (`.github/workflows/publish.yaml`): Package publishing workflow
+- **Version** (`.github/workflows/version.yaml`): Version management workflow
-# Support
+## Support
If you have a question on how to use the product, please see our
[support guide](https://github.com/hashgraph/.github/blob/main/SUPPORT.md).
-# Contributing
+## Contributing
Contributions are welcome. Please see the
[contributing guide](https://github.com/hashgraph/.github/blob/main/CONTRIBUTING.md)
to see how you can get involved.
-# Code of conduct
+## Code of Conduct
This project is governed by the
[Contributor Covenant Code of Conduct](https://github.com/hashgraph/.github/blob/main/CODE_OF_CONDUCT.md). By
participating, you are expected to uphold this code of conduct. Please report unacceptable behavior
to [oss@hedera.com](mailto:oss@hedera.com).
-# License
+## License
[Apache License 2.0](LICENSE)
-# 🔐 Security
+## Security
-Please do not file a public ticket mentioning the vulnerability. Refer to the security policy defined in the [SECURITY.md](https://github.com/hashgraph/stablecoin-studio/blob/main/SECURITY.md).
+Please do not file a public ticket mentioning the vulnerability. Refer to the security policy defined in the [SECURITY.md](SECURITY.md).
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index f30d49329..000000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Security Policy
-
-## Reporting a Vulnerability
-
-Please do not file a public ticket mentioning the vulnerability. To report a vulnerability, please send an email to .
diff --git a/backend/Dockerfile b/backend/Dockerfile
index edac50c7b..c063d9634 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -14,12 +14,18 @@ ENV NODE_ENV development
# RUN addgroup --system --gid 1001 node
# RUN adduser --system --uid 1001 node
-# Copy source code into app folder
-COPY --chown=node:node . .
+# Copy workspace root files
+COPY --chown=node:node package*.json ./
-# Install dependencies
+# Install all workspace dependencies
RUN npm ci
+# Copy backend source code
+COPY --chown=node:node backend ./backend
+
+# Set working directory to backend
+WORKDIR /app/backend
+
# Set Docker as a non-root user
USER node
@@ -38,16 +44,23 @@ ENV NODE_ENV production
# RUN addgroup --system --gid 1001 node
# RUN adduser --system --uid 1001 node
-# In order to run `yarn build` we need access to the Nest CLI.
-# Nest CLI is a dev dependency.
-COPY --chown=node:node --from=development /app/node_modules ./node_modules
-# Copy source code
-COPY --chown=node:node . .
+# Copy workspace root files
+COPY --chown=node:node package*.json ./
+
+# Install all workspace dependencies
+RUN npm ci
+
+# Copy backend source code
+COPY --chown=node:node backend ./backend
+
+# Set working directory to backend
+WORKDIR /app/backend
# Generate the production build. The build script runs "nest build" to compile the application.
RUN npm run build
# Install only the production dependencies and clean cache to optimize image size.
+WORKDIR /app
RUN npm ci --production && npm cache clean --force
# Set Docker as a non-root user
@@ -68,8 +81,8 @@ ENV NODE_ENV production
# RUN addgroup --system --gid 1001 node
# RUN adduser --system --uid 1001 node
-# Copy only the necessary files
-COPY --chown=node:node --from=build /app/dist dist
+# Copy only the necessary files from backend build
+COPY --chown=node:node --from=build /app/backend/dist dist
COPY --chown=node:node --from=build /app/node_modules node_modules
# Set Docker as non-root user
diff --git a/backend/README.md b/backend/README.md
deleted file mode 100644
index d6664caff..000000000
--- a/backend/README.md
+++ /dev/null
@@ -1,329 +0,0 @@
-
-
-# Stablecoin Studio - Backend
-
-[](LICENSE)
-
-
-
-### Table of Contents
-
-- **[Context](#context)**
-- **[Architecture](#architecture)**
-- **[Overview](#overview)**
- - [Add a transaction](#add-a-transaction)
- - [Sign a transaction](#sign-a-transaction)
- - [Update a transaction](#update-a-transaction)
- - [Delete a transaction](#delete-a-transaction)
- - [Retrieve all transactions](#retrieve-all-transactions)
- - [Retrieve transactions for public key](#retrieve-transactions-for-public-key)
-- **[Technologies](#technologies)**
-- **[Installation](#installation)**
-- **[Build](#build)**
-- **[Run](#run)**
-- **[Configuration](#configuration)**
-- **[Testing](#testing)**
-- **[Contributing](#contributing)**
-- **[Code of conduct](#code-of-conduct)**
-- **[License](#license)**
-
-# Context
-
-The backend module is meant to be used in combination with the __Hedera StableCoin Studio__.
-
-Its purpose is to enable multisignatures for stable coins management operations.
-
-> Only _single level_ multikeys are supported for now. Keys lists/Threshold keys associated to accounts cannot contain key lists/threshold keys themselves as keys.
-
-Whenever users need to submit to the DLT network a transaction (Cash In, Freeze, ...) associated to an account that has multiple keys (key list or threshold keys) they will have the possibility to interact with the backend in the following way:
-
-- They will first add the "raw transaction" (unsigned string of bytes) to the backend's database using the backend's api.
-- After the transaction is created, key owners will have the possibility to asyncronously sign the transaction.
-- Once all the required keys have signed the transaction, anyone can retrieve the transaction and its signatures, concatenate them and submit it to the Hedera network. (*)
-
-> (*) If the transaction is not submited by anyone yet it has been properly signed, the __scheduled job__ will pick it up and submit it automatically.
-
-# Architecture
-
-The backend is made of two components:
-- **API**: the api interacts with the underlying database and exposes 4 functionalities
- - _Add a transaction_: allows for a new, unsigned transaction to be added to the database.
- - _Sign a transaction_: allows for a transaction to be signed by one of the keys associated to the account the transaction belongs to.
- - _Update a transaction_: allows for a transaction fields to be updated (status).
- - _Remove a transaction_: allows for a transaction to be removed from the database.
- - _Retrieve transactions_: allows for transactions to be retrieved, either all of them or those that are associated to a given public key.
-- **Database**: the db where transactions are stored waiting to be signed by all account's keys before submitting them to the Hedera DLT. It has one table with the following columns.
- - _id_: Every transaction has UUID that uniquely identifies it within the database.
- - _transactionMessage_: The content of the unsigned raw transaction submitted when creating a new transaction.
- - _description_: Description of what the _transactionMessage_ does. This is useful so that users know what the transaction is supposed to do before signing it.
- - _hederaAccountId_: The hedera account the transaction belongs to.
- - _signatures_: List of signatures already added to the transaction.
- - _keyList_: List of public keys associated to the account the transaction belongs to. These are the keys that have the right to sign the transaction.
- - _signedKeys_: List of public keys that have already signed the transaction (their signatures have been added to _signatures_).
- - _startDate_: The date and time at which the transaction can eb submitted to the DLT.
- - _status_: Current status of the transaction. There are two options:
- - PENDING: transaction signature is still in progress.
- - SIGNED: all required keys have already signed the transaction, we can submit it to the Hedera DLT.
- - EXPIRED : all transactions that cannot be submitted to the DLT anymore. Transactions can be submitted within a 3-minute window from their startDate. After that, the transaction is considered "expired" and can no longer be submitted (it must be recreated).
- - ERROR : a transaction that is no longer valid. Some transactions are valid when created but become invalid due to subsequent transactions submitted immediately after their creation. In such cases, the transaction status is set to "error" by the "scheduled job" when trying to submit it.
- - EXECUTED : a transaction that has been properly submitted to the DLT.
- - _threshold_: minimum number of keys that must sign the transaction before we can submit to the network (update its status to _SIGNED_).
-- **Scheduled Job**: the scheduled job is a job that runs every 30 seconds (by default but it can be configured in the .env file) and scans the DB looking for two types of transactions.
- - Transactions ready to submit : transactions that have been signed by all the necessary keys and we are currently within its 3-minute validity time windows (3 minutes from its start date). The scheduled job will pick these transactions and submit them to the DLT.
- - If the transaction succeeds, its status is set to "EXECUTED".
- - If the transaction fails, its status is set to "ERROR".
- - Expired Transactions : These are "pending" or "signed" transactions whose start date is more than 3 minutes ago. The scheduled job will change the status of these transactions to "EXPIRED".
-
-# Overview
-
-## Add a transaction
-
- - __Path__ : /v1/transactions
- - __HTTP Method__ : POST
- - __Body__ :
- ```
-{
- "payload": "transaction_raw_message",
- "description": "transaction_short_description",
- "accountId": "your_account_id",
- "keyList": ["PK1", "PK2", ...],
- "threshold": "number"
-}
- ```
- - __Logic__ :
- - Action : transaction is added to the DB.
- - __Status code__ :
- - 201 Created: Transaction added successfully.
- - 400 Bad Request: Invalid request payload.
- - 500 Internal Server Error: An error occurred during the process.
-
- - __Response__ :
-```
-{
- "transactionId": "generated_transaction_ID"
-}
-```
-
-## Sign a transaction
-
- - __Path__ : /v1/transactions/{transactionId}/signature
- - __HTTP Method__ : PUT
- - __Body__ :
- ```
-{
- "signedTransactionMessage": "transaction_signed_message",
- "publicKey": "public_key_used_for_signing"
-}
- ```
- - __Logic__ :
- - Success :
- - transaction id exists
- - public key is part of the remaining key list (has the right to sign)
- - body’s signatures matches the provided public key
- - the signature added to the body is indeed associated to the provided public key (compare with the current transaction body)
- - Action :
- - updates the Body of the transaction in the DB
- - removes the public key from the list of “Remaining keys”
- - Updates the threshold
- - __Status code__ :
- - 204 No content: Transaction updated successfully.
- - 400 Bad Request: Invalid _transactionId_ format.
- - 401 Unauthorized: Unauthorized key.
- - 404 Not Found: _transactionId_ could not be found.
- - 409 Conflict: _transactionId_ already signed by the provided key.
- - 500 Internal Server Error: An error occurred during the process.
-
-## Update a transaction
-
- - __Path__ : /v1/transactions/{transactionId}/update
- - __HTTP Method__ : PUT
- - __Body__ :
- ```
-{
- "status": "new_status",
-}
- ```
- - __Logic__ :
- - Success :
- - transaction id exists
- - status is a valid status
- - Action :
- - updates the Transaction status
- - __Status code__ :
- - 204 No content: Transaction updated successfully.
- - 400 Bad Request: Invalid _transactionId_ format or _status_ value.
- - 401 Unauthorized: Unauthorized key.
- - 404 Not Found: _transactionId_ could not be found.
- - 409 Conflict: _transactionId_ already signed by the provided key.
- - 500 Internal Server Error: An error occurred during the process.
-
-## Delete a transaction
-
- - __Path__ : /v1/transactions/{transactionId}
- - __HTTP Method__ : DELETE
- __Logic__ :
- - Success :
- - transaction id exists
- - Action : removes transaction from the DB.
- - __Status code__ :
- - 204 No content: Transaction removed successfully.
- - 400 Bad Request: Invalid _transactionId_ format.
- - 404 Not Found: _transactionId_ could not be found.
- - 500 Internal Server Error: An error occurred during the process.
-
-## Retrieve All transactions
-
- - __Path__ : /v1/transactions
- - __HTTP Method__ : GET
- - __Query Params__ :
- - _network_: network name (optional)
- - _publicKey_: public key (optional)
- - _status_: transaction status (optional)
- - _page_: page number (optional)
- - _limit_: number of transactions per page (optional)
- - _hederaAccountId_: account id (optional)
- - __Logic__ :
- - Action: Returns all the transactions from the DB (paginated response), optionally filtered by network, publicKey, account id and status.
- - __Status code__ :
- - 200 OK.
- - 500 Internal Server Error: An error occurred during the process.
- - __Response__ :
-```
-[
- {
- "id" :"transaction_id",
- "transaction_message": "hexadecimal_array_of_bytes",
- "description": "transaction_short_description",
- "hedera_account_id": "your_account_id",
- "signatures": ["signature_1", "signature_2", ...],
- "key_list": ["PK1", "PK2", ...],
- "signed_keys": ["PK1", "PK2", ...],
- "status": "transaction_status",
- "threshold":"number",
- "signatures": ["signature_1", "signature_2", ...]
- },
- {...}
-]
-```
-
-## Retrieve transactions by transactionId
-
- - __Path__ : /v1/transactions/{transactionId}
- - __HTTP Method__ : GET
- __Logic__ :
- - Action : returns all the transaction from the DB for a specific transactionId and status (PENDING/SIGNED) (paginated response).
- - __Status code__ :
- - 200 OK.
- - 500 Internal Server Error: An error occurred during the process.
- - __Response__ :
-```
-[
- {
- "id" :"transaction_id",
- "transaction_message": "hexadecimal_array_of_bytes",
- "description": "transaction_short_description",
- "hedera_account_id": "your_account_id",
- "signatures": ["signature_1", "signature_2", ...],
- "key_list": ["PK1", "PK2", ...],
- "signed_keys": ["PK1", "PK2", ...],
- "status": "transaction_status",
- "threshold":"number",
- "signatures": ["signature_1", "signature_2", ...]
- },
- {...}
-]
-```
-
-## Delete all transactions
-This functionality is not exposed through the API. It is meant to be used for testing purposes only.
-To delete all transactions from the DB, run the following command:
-```shell
-npm run deleteAllTransactions
-```
-
-# Technologies
-
-- Typescript
-- NestJS
-- TypeORM
-- Winston
-- Postgres
-- Docker
-
-# Installation
-
-The command below can be used to install the official release from the NPM repository. This version may not reflect the most recent changes to the main branch of this repository.
-
-```bash
-npm install -g @hashgraph/stablecoin-npm-backend
-```
-
-# Build
-
-Run `npm install`. This will create and populate `node_modules` and build the project and dependencies.
-
-Then run `npm run build`. This will create and populate the `dist` folder with the transpiled javascript files.
-
-# Run
-
-In order to run the backend you will need to execute the docker compose yaml file that defines the entire application (DB + API).
-
-Run `docker compose up -d --build`. This will start two containers (one for the API, another one for the DB), their respectives volumes and the network for them to communicate with each other.
-
-The application will use two ports (defined in the .env file):
- - Port `SERVER_PORT`: This is the API port, it can be accessed from outside the docker project.
- - Port `DB_PORT`: This is the DB port, it is only accessible from within the docker network.
-
-# Configuration
-
-There is a `.env` file that must be used to configure the backend. These are the configuration parameters:
-
-- `COMPOSE_PROJECT_NAME`: Name of the docker compose project.
-- `CONTAINER_BACK_NAME`: Name of the container running the NestJS API.
-- `CONTAINER_DB_NAME`: Name of the container running the postgres DB.
-- `DOCKER_NETWORK_NAME`: Name of the docker compose network.
-- `SERVER_HOST`: API server name.
-- `SERVER_PORT`: API port. This port will be exposed outside of the docker network so that anyone can reach it.
-- `DB_HOST`: DB server name.
-- `DB_PORT`: DB port. This port will not be exposed outside of the docker network, which means that it is only accessible to the API.
-- `DB_USER`: DB admin user name.
-- `DB_PASSWORD`: DB admin user password.
-- `DB_NAME`: DB name.
-- `ORIGIN`: List of urls that are accepted in the HTTP header "Origin". If the API endpoints are invoked from a different url, the request will fail.
-- `MAX_LOG_FILESIZE`: Max size of the logging files used by the Winston file rotation policy. If a log file reaches this size, it will be zipped and a new file will be created.
-- `LOG_LEVEL`: Minimum log level to be included in the loging files.
-- `FILE_NAME`: Log file name pattern and localtion.
-- `DATE_PATTERN`: Log file date pattern.
-- `AUTO_SUBMIT_JOB_FREQUENCY` : Cron format string that defines the frequency at which the auto submit job runs
-
-
-# Testing
-
-## Jest
-
-The project uses [Jest](https://jestjs.io/es-ES/) for testing.
-
-## Run
-
-Tests may be run using the following command
-
-```shell
-npm run test
-```
-
-# Contributing
-
-Contributions are welcome. Please see the
-[contributing guide](https://github.com/hashgraph/.github/blob/main/CONTRIBUTING.md)
-to see how you can get involved.
-
-# Code of conduct
-
-This project is governed by the
-[Contributor Covenant Code of Conduct](https://github.com/hashgraph/.github/blob/main/CODE_OF_CONDUCT.md). By
-participating, you are expected to uphold this code of conduct. Please report unacceptable behavior
-to [oss@hedera.com](mailto:oss@hedera.com).
-
-# License
-
-[Apache License 2.0](../LICENSE.md)
diff --git a/backend/compose.yaml b/backend/compose.yaml
index e190953b5..3d87a0bb5 100644
--- a/backend/compose.yaml
+++ b/backend/compose.yaml
@@ -1,21 +1,17 @@
-version: '3.9'
-
services:
# Uses base image from node and maps local needed files to the container
backend:
build:
- context: .
- dockerfile: Dockerfile
+ context: ..
+ dockerfile: backend/Dockerfile
target: development
container_name: ${CONTAINER_BACK_NAME} # This is the name of the container
image: multisig-back:latest # This is the name of the image that will be created
restart: unless-stopped
volumes:
- - .:/app
- # This ensures that the NestJS container manages the node_modules folder
- # rather than synchronizes it with the host machine
- - /app/node_modules
+ - ..:/app
- log:/var/lib/logs
+ working_dir: /app/backend
ports:
- '${SERVER_PORT}:${SERVER_PORT}'
networks:
@@ -30,7 +26,7 @@ services:
- DB_PASSWORD=${DB_PASSWORD}
depends_on:
- ${CONTAINER_DB_NAME}
- command: npx nest start --watch
+ command: node ../node_modules/.bin/nest start --watch
db:
image: postgres:14.11-alpine3.19
diff --git a/backend/package.json b/backend/package.json
index 51509e8cf..f853be9c7 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,6 +1,6 @@
{
"name": "@hashgraph/stablecoin-npm-backend",
- "version": "4.0.2",
+ "version": "4.1.0",
"description": "",
"author": "",
"license": "Apache-2.0",
@@ -26,7 +26,7 @@
"pre-commit": "npm run lint && npm run prettier"
},
"dependencies": {
- "@hashgraph/sdk": "2.51.0",
+ "@hiero-ledger/sdk": "2.79.0",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.0",
"@nestjs/core": "^10.0.0",
diff --git a/backend/src/jobs/autoSubmit.service.ts b/backend/src/jobs/autoSubmit.service.ts
index 391257c2b..1330ad11a 100644
--- a/backend/src/jobs/autoSubmit.service.ts
+++ b/backend/src/jobs/autoSubmit.service.ts
@@ -29,7 +29,7 @@ import {
TransactionResponse,
TransactionReceipt,
Status,
-} from '@hashgraph/sdk';
+} from '@hiero-ledger/sdk';
import { GetTransactionsResponseDto } from '../transaction/dto/get-transactions-response.dto';
import { hexToUint8Array } from '../utils/utils';
import { LoggerService } from '../logger/logger.service.js';
diff --git a/backend/src/transaction/transaction.service.ts b/backend/src/transaction/transaction.service.ts
index 300134e79..218856a5f 100644
--- a/backend/src/transaction/transaction.service.ts
+++ b/backend/src/transaction/transaction.service.ts
@@ -44,7 +44,7 @@ import {
} from '../common/exceptions/domain-exceptions';
import { TransactionStatus } from './status.enum';
import { Network } from './network.enum';
-import { Client, Transaction as TransactionSdk } from '@hashgraph/sdk';
+import { Client, Transaction as TransactionSdk } from '@hiero-ledger/sdk';
@Injectable()
export default class TransactionService {
diff --git a/backend/src/utils/utils.ts b/backend/src/utils/utils.ts
index 1220dee61..fb10a12a3 100644
--- a/backend/src/utils/utils.ts
+++ b/backend/src/utils/utils.ts
@@ -21,7 +21,7 @@
import * as nacl from 'tweetnacl';
import * as elliptic from 'elliptic';
import { keccak256 } from 'ethereum-cryptography/keccak';
-import { Transaction } from '@hashgraph/sdk';
+import { Transaction } from '@hiero-ledger/sdk';
export function verifySignature(
publicKeyHex: string,
diff --git a/backend/test/transaction/transaction.service.spec.ts b/backend/test/transaction/transaction.service.spec.ts
index 3564adb1f..62d3cb880 100644
--- a/backend/test/transaction/transaction.service.spec.ts
+++ b/backend/test/transaction/transaction.service.spec.ts
@@ -28,7 +28,7 @@ import { SignTransactionRequestDto } from '../../src/transaction/dto/sign-transa
import TransactionMock, { DEFAULT } from './transaction.mock';
import { LoggerService } from '../../src/logger/logger.service';
import { TransactionStatus } from '../../src/transaction/status.enum';
-import { Client } from '@hashgraph/sdk';
+import { Client } from '@hiero-ledger/sdk';
describe('Transaction Service Test', () => {
let service: TransactionService;
diff --git a/cli/README.md b/cli/README.md
deleted file mode 100644
index 2f5fe998f..000000000
--- a/cli/README.md
+++ /dev/null
@@ -1,376 +0,0 @@
-
-
-# Stablecoin Studio - Command Line Interface (CLI)
-
-[](../LICENSE.md)
-
-