Skip to content

Commit a72fc12

Browse files
committed
Merge branch 'refactor/364-error-handling-patterns' of https://github.com/Oluwasuyi-Timilehin/teachLink_contract into refactor/364-error-handling-patterns
2 parents 417c933 + 4e8cec6 commit a72fc12

171 files changed

Lines changed: 19246 additions & 1205 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/dependabot.yml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: cargo
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
day: monday
8+
open-pull-requests-limit: 10
9+
labels:
10+
- dependencies
11+
- rust
12+
commit-message:
13+
prefix: "chore(deps)"
14+
reviewers:
15+
- Spagero763
16+
17+
- package-ecosystem: github-actions
18+
directory: /
19+
schedule:
20+
interval: weekly
21+
day: monday
22+
open-pull-requests-limit: 5
23+
labels:
24+
- dependencies
25+
- github-actions
26+
commit-message:
27+
prefix: "chore(deps)"

‎.github/workflows/ci.yml‎

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ on:
66
pull_request:
77

88
jobs:
9-
rust:
9+
quality:
10+
name: Code Quality & Format Checks
1011
runs-on: ubuntu-latest
1112
steps:
12-
- uses: actions/checkout@v4
13+
- uses: actions/checkout@v6
1314

1415
- name: Install Rust toolchain
1516
uses: dtolnay/rust-toolchain@stable
1617
with:
1718
components: rustfmt, clippy
18-
targets: wasm32v1-none
19+
targets: wasm32-unknown-unknown
1920

2021
- name: Cache cargo
2122
uses: Swatinem/rust-cache@v2
@@ -26,11 +27,50 @@ jobs:
2627
- name: Run clippy linter
2728
run: cargo clippy --workspace --all-features -- -D warnings
2829

30+
build-and-test:
31+
name: Build & Test
32+
needs: quality
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v6
36+
37+
- name: Install Rust toolchain
38+
uses: dtolnay/rust-toolchain@stable
39+
with:
40+
components: rustfmt, clippy
41+
targets: wasm32-unknown-unknown
42+
43+
- name: Cache cargo
44+
uses: Swatinem/rust-cache@v2
45+
2946
- name: Build WASM (release)
30-
run: cargo build --target wasm32v1-none --release
47+
run: cargo build --target wasm32-unknown-unknown --release
3148

3249
- name: Run unit tests
3350
run: cargo test --workspace --lib
3451

3552
- name: Run integration tests
3653
run: cargo test --workspace --test cross_chain_integration
54+
55+
security-audit:
56+
runs-on: ubuntu-latest
57+
steps:
58+
- uses: actions/checkout@v6
59+
60+
- name: Install Rust toolchain
61+
uses: dtolnay/rust-toolchain@stable
62+
63+
- name: Cache cargo
64+
uses: Swatinem/rust-cache@v2
65+
66+
- name: Install cargo-audit
67+
run: cargo install cargo-audit --locked
68+
69+
- name: Run dependency vulnerability audit
70+
run: cargo audit
71+
72+
- name: Install cargo-deny
73+
run: cargo install cargo-deny --locked
74+
75+
- name: Check dependency licenses and advisories
76+
run: cargo deny check
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Generate Changelog
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
inputs:
9+
version:
10+
description: 'Version to generate changelog for (e.g., v1.0.0)'
11+
required: false
12+
13+
jobs:
14+
changelog:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Setup Node.js
23+
uses: actions/setup-node@v6
24+
with:
25+
node-version: '18'
26+
27+
- name: Generate Changelog
28+
run: node scripts/generate-changelog.js
29+
30+
- name: Commit Changelog
31+
run: |
32+
git config --local user.email "action@github.com"
33+
git config --local user.name "GitHub Action"
34+
git add CHANGELOG.md
35+
git commit -m "docs(changelog): update for release [skip ci]" || echo "No changes to commit"
36+
git push origin HEAD:main

‎.github/workflows/regression.yml‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ jobs:
99
name: Tests & Regression Detection
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v4
12+
- uses: actions/checkout@v6
1313

1414
- name: Install Rust toolchain
1515
uses: dtolnay/rust-toolchain@stable
1616
with:
1717
components: rustfmt, clippy
18-
targets: wasm32v1-none
18+
targets: wasm32-unknown-unknown
1919

2020
- name: Cache cargo
2121
uses: Swatinem/rust-cache@v2
@@ -34,13 +34,17 @@ jobs:
3434
- name: Check performance regressions
3535
run: bash scripts/check_performance.sh
3636

37+
- name: Enforce performance budgets
38+
if: always()
39+
run: bash scripts/enforce_budgets.sh --verbose
40+
3741
- name: Generate test report
3842
if: always()
3943
run: bash scripts/generate_test_report.sh
4044

4145
- name: Upload test report
4246
if: always()
43-
uses: actions/upload-artifact@v4
47+
uses: actions/upload-artifact@v7
4448
with:
4549
name: test-report-${{ github.sha }}
4650
path: reports/

‎.jscpd.json‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"threshold": 5,
3+
"reporters": ["html", "console", "json"],
4+
"ignore": [
5+
"**/target/**",
6+
"**/tests/**",
7+
"**/benches/**",
8+
"**/scripts/**",
9+
"**/*.json",
10+
"**/*.md"
11+
],
12+
"absolute": true,
13+
"output": "reports/duplication"
14+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"specId": "cddaa1a2-6be0-42a9-b68f-c2286012814d", "workflowType": "requirements-first", "specType": "feature"}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Requirements Document
2+
3+
## Introduction
4+
5+
This feature addresses the refactoring of large, complex functions across the TeachLink Rust smart contract codebase. The codebase spans multiple Soroban/ink! contracts including `teachlink`, `insurance`, `documentation`, `marketplace`, `governance`, and supporting modules. Several functions and contract implementations have grown to hundreds of lines, mixing multiple responsibilities, making them difficult to read, test, and maintain.
6+
7+
The goal is to systematically identify overly large or complex functions, decompose them into smaller, single-responsibility units, improve code readability through consistent naming and structure, enhance testability by isolating logic into pure or near-pure helper functions, and add inline documentation to all public and non-trivial private functions.
8+
9+
## Glossary
10+
11+
- **Refactoring_Tool**: The automated or manual process responsible for identifying, decomposing, and documenting functions in the codebase.
12+
- **Target_Function**: A function identified as a candidate for refactoring based on complexity or size thresholds.
13+
- **Helper_Function**: A smaller, focused function extracted from a Target_Function to handle a single sub-responsibility.
14+
- **Complexity_Threshold**: The measurable criteria used to identify a Target_Function (e.g., line count, cyclomatic complexity, number of responsibilities).
15+
- **Doc_Comment**: An inline Rust documentation comment (`///`) attached to a function, struct, or module.
16+
- **Contract_Module**: A Rust source file or module within the `contracts/` directory (e.g., `insurance/src/lib.rs`, `teachlink/src/lib.rs`).
17+
- **Test_Suite**: The collection of unit and integration tests associated with a Contract_Module.
18+
- **Single_Responsibility**: The principle that a function performs exactly one well-defined task.
19+
- **Pure_Function**: A function with no side effects whose output depends only on its inputs.
20+
- **Cyclomatic_Complexity**: A quantitative measure of the number of linearly independent paths through a function's source code.
21+
22+
---
23+
24+
## Requirements
25+
26+
### Requirement 1: Identify Refactoring Candidates
27+
28+
**User Story:** As a developer, I want to identify all functions that exceed complexity or size thresholds, so that I have a clear, prioritized list of refactoring targets.
29+
30+
#### Acceptance Criteria
31+
32+
1. THE Refactoring_Tool SHALL identify all functions in Contract_Modules that exceed 50 lines of code.
33+
2. THE Refactoring_Tool SHALL identify all functions in Contract_Modules with a Cyclomatic_Complexity score greater than 10.
34+
3. THE Refactoring_Tool SHALL identify all functions that handle more than one distinct responsibility (e.g., validation, storage mutation, and token transfer within a single function body).
35+
4. WHEN identification is complete, THE Refactoring_Tool SHALL produce a prioritized list of Target_Functions ordered by descending line count and Cyclomatic_Complexity.
36+
5. THE Refactoring_Tool SHALL include the Contract_Module path, function name, line count, and estimated Cyclomatic_Complexity for each entry in the prioritized list.
37+
38+
---
39+
40+
### Requirement 2: Decompose Large Functions
41+
42+
**User Story:** As a developer, I want large functions broken into smaller, focused Helper_Functions, so that each unit of code has a Single_Responsibility and is easier to understand.
43+
44+
#### Acceptance Criteria
45+
46+
1. WHEN a Target_Function is refactored, THE Refactoring_Tool SHALL extract each distinct responsibility into a separate Helper_Function.
47+
2. THE Refactoring_Tool SHALL ensure each Helper_Function does not exceed 30 lines of code.
48+
3. THE Refactoring_Tool SHALL ensure each Helper_Function has a Cyclomatic_Complexity score of 5 or less.
49+
4. WHEN a Target_Function is decomposed, THE Refactoring_Tool SHALL preserve the original function's public signature so that existing callers require no changes.
50+
5. WHEN a Target_Function is decomposed, THE Refactoring_Tool SHALL ensure the refactored code produces identical outputs for all inputs that were valid before refactoring.
51+
6. IF a Helper_Function operates only on its input parameters and returns a value without accessing external state, THEN THE Refactoring_Tool SHALL declare it as a Pure_Function (i.e., a `fn` with no `Env` or storage access).
52+
7. THE Refactoring_Tool SHALL apply decomposition to all identified Target_Functions across all Contract_Modules, including `contracts/insurance/src/lib.rs`, `contracts/teachlink/src/lib.rs`, and all modules under `contracts/teachlink/src/`.
53+
54+
---
55+
56+
### Requirement 3: Preserve Behavioral Correctness
57+
58+
**User Story:** As a developer, I want refactored functions to behave identically to the originals, so that no regressions are introduced during the refactoring process.
59+
60+
#### Acceptance Criteria
61+
62+
1. WHEN a Target_Function is refactored, THE Test_Suite SHALL pass all pre-existing tests without modification to test assertions.
63+
2. THE Refactoring_Tool SHALL not alter the return type or error variants of any public function during decomposition.
64+
3. THE Refactoring_Tool SHALL not alter the storage keys read or written by any Contract_Module during decomposition.
65+
4. IF a Target_Function emits contract events, THEN THE Refactoring_Tool SHALL ensure the refactored version emits the same events with the same data.
66+
5. FOR ALL valid inputs to a Target_Function before refactoring, the refactored function SHALL produce an equivalent result (round-trip behavioral equivalence property).
67+
68+
---
69+
70+
### Requirement 4: Improve Code Readability
71+
72+
**User Story:** As a developer, I want refactored code to follow consistent naming and structural conventions, so that the codebase is easier to navigate and understand.
73+
74+
#### Acceptance Criteria
75+
76+
1. THE Refactoring_Tool SHALL name each Helper_Function using a verb-noun pattern that describes its single action (e.g., `validate_risk_factors`, `calculate_weighted_score`, `transfer_premium`).
77+
2. THE Refactoring_Tool SHALL group related Helper_Functions within the same `impl` block or module as the Target_Function they were extracted from.
78+
3. THE Refactoring_Tool SHALL remove dead code, unused variables, and redundant comments identified during decomposition.
79+
4. WHEN a Target_Function contains inline magic numbers or string literals, THE Refactoring_Tool SHALL extract them into named constants with descriptive identifiers.
80+
5. THE Refactoring_Tool SHALL ensure all refactored files compile without warnings under `cargo clippy` with the project's existing clippy configuration.
81+
82+
---
83+
84+
### Requirement 5: Enhance Testability
85+
86+
**User Story:** As a developer, I want refactored Helper_Functions to be independently testable, so that unit tests can target individual logic units without requiring full contract setup.
87+
88+
#### Acceptance Criteria
89+
90+
1. WHEN a Helper_Function is a Pure_Function, THE Test_Suite SHALL include at least one unit test that calls the Helper_Function directly without constructing a Soroban `Env`.
91+
2. THE Refactoring_Tool SHALL ensure that validation logic (e.g., bounds checking, input sanitization) is extracted into dedicated Helper_Functions that accept only primitive or struct inputs.
92+
3. THE Refactoring_Tool SHALL ensure that calculation logic (e.g., premium computation, risk scoring, royalty splits) is extracted into dedicated Pure_Functions.
93+
4. WHEN a calculation Helper_Function is extracted, THE Test_Suite SHALL include a property-based test verifying that the function's output remains within its documented valid range for all valid inputs.
94+
5. THE Refactoring_Tool SHALL ensure that storage access logic is isolated from business logic so that business logic functions can be tested without storage mocking.
95+
96+
---
97+
98+
### Requirement 6: Add Inline Documentation
99+
100+
**User Story:** As a developer, I want all public and non-trivial private functions to have Doc_Comments, so that the codebase is self-documenting and easier to onboard new contributors.
101+
102+
#### Acceptance Criteria
103+
104+
1. THE Refactoring_Tool SHALL add a `///` Doc_Comment to every public function in all Contract_Modules that does not already have one.
105+
2. THE Refactoring_Tool SHALL add a `///` Doc_Comment to every Helper_Function extracted during decomposition.
106+
3. WHEN a Doc_Comment is added to a function, THE Refactoring_Tool SHALL include a one-sentence description of the function's purpose, its parameters (using `# Arguments` section), and its return value or error variants (using `# Returns` and `# Errors` sections) where applicable.
107+
4. THE Refactoring_Tool SHALL add module-level `//!` documentation to any Contract_Module file that lacks it, describing the module's overall responsibility.
108+
5. WHEN a function has non-obvious preconditions or invariants, THE Refactoring_Tool SHALL document them in a `# Panics` or `# Preconditions` section within the Doc_Comment.
109+
6. THE Refactoring_Tool SHALL ensure all Doc_Comments are valid Rust documentation syntax and do not produce warnings under `cargo doc`.
110+
111+
---
112+
113+
### Requirement 7: Maintain Contract Interface Stability
114+
115+
**User Story:** As a developer, I want the public contract interface to remain unchanged after refactoring, so that deployed clients and external integrations are not broken.
116+
117+
#### Acceptance Criteria
118+
119+
1. THE Refactoring_Tool SHALL not rename, remove, or change the parameter types of any `#[contractimpl]` public function during refactoring.
120+
2. THE Refactoring_Tool SHALL not change the `#[contracttype]` definitions of any types used in public function signatures.
121+
3. WHEN refactoring a Soroban contract, THE Refactoring_Tool SHALL ensure the contract compiles to a valid WASM artifact with `cargo build --target wasm32-unknown-unknown --release`.
122+
4. THE Refactoring_Tool SHALL not introduce new public functions into `#[contractimpl]` blocks unless they are explicitly required to support decomposition of a Target_Function.
123+
5. IF a Contract_Module has existing test snapshots (e.g., in `test_snapshots/`), THEN THE Refactoring_Tool SHALL ensure all snapshot tests continue to pass after refactoring.

0 commit comments

Comments
 (0)