Thank you for your interest in contributing to the Scallop Python SDK!
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/sui-scallop-sdk-python.git cd sui-scallop-sdk-python - Install development dependencies:
pip install -e ".[dev]" - Install pre-commit hooks:
pre-commit install
make test
# or
pytest tests/ -v# Check lint
make lint
# Auto-format
make format
# Run all checks (lint + typecheck + test)
make allmake typecheck
# or
mypy src/sui_scallop_sdkThis project follows Conventional Commits:
feat: add new lending operation
fix: resolve oracle price update issue
docs: update README examples
refactor: simplify BCS serialization
test: add tests for flash loan
Pre-commit hooks will validate commit message format automatically.
- Create a new branch for your feature/fix
- Make your changes
- Ensure all checks pass:
make all - Update
CHANGELOG.mdif the change is user-facing - Submit a pull request using the PR template
This section codifies lessons learned from the v0.2.1 audit, where 12 bugs (5 critical) went undetected by the existing test suite.
-
Semantic over Structural: Tests must verify values, not just that a method exists or returns something.
- ❌
assert isinstance(result, int)— only checks type - ✅
assert result.result_index == 1— checks the actual value is correct
- ❌
-
Error paths are mandatory: Every
try/except,if/else, and validation branch must have a corresponding test.- If a method can raise
ValueError, test that it does with the correct message. - If a method silently catches exceptions, test that it logs them.
- If a method can raise
-
Mock external dependencies, not logic: Use
unittest.mock.patchfor RPC calls, HTTP requests, and Oracle APIs. Never mock the unit under test. -
Regression tests for every bug fix: Each resolved bug must have a dedicated regression test that would fail if the bug were reintroduced.
| Category | Description | Example |
|---|---|---|
| Happy path | Normal usage with valid inputs | test_deposit_adds_move_call |
| Argument values | Verify exact arguments passed to downstream calls | test_deposit_uses_correct_package_id |
| Edge cases | Boundary values, empty inputs, None, zero | test_health_factor_zero_borrow_returns_none |
| Error paths | Invalid inputs, network failures, malformed data | test_invalid_base64_raises_config_error |
| Regression | Specific test for each known bug | test_deep_feed_id_not_sol_bug5 |
When adding or modifying a module, verify:
- All public methods have at least one test
- All factory methods (
from_config,from_env) are tested - Return values are checked for correctness, not just type
- Dictionary/config lookups are tested for completeness (e.g., every coin has a feed ID)
- String operations use
removeprefix/removesuffix, neverlstrip/rstripfor prefix/suffix removal - Docstrings match actual parameter units (seconds vs milliseconds, etc.)
- Quick methods (
*_quick) have separate tests from their base methods - Mocked tests verify argument values passed to mocks, not just call counts
# Run all tests with coverage
pytest tests/ --cov=sui_scallop_sdk --cov-report=term-missing
# Run specific test file
pytest tests/test_oracle.py -v
# Run tests matching a pattern
pytest tests/ -k "test_deep" -v| Test File | Covers |
|---|---|
test_constants.py |
Coin metadata, address normalization, dictionary consistency |
test_config.py |
ScallopConfig init, from_env, validation |
test_exceptions.py |
All exception classes, error parsing |
test_models.py |
Pydantic models, edge cases |
test_crypto.py |
Keypair formats (base64, hex, bech32), signing, address derivation |
test_client.py |
ScallopClient init, from_config, from_env, keypair parsing |
test_bcs.py |
BCS serialization, boundary values, type tags |
test_utils.py |
Coin utilities, amount formatting/parsing |
test_rpc_mocked.py |
All RPC methods (mocked httpx), sync + async |
test_rpc.py |
RPC integration tests (real network) |
test_oracle.py |
Oracle client, Pyth feeds, Hermes API (mocked) |
test_query_parsing.py |
Query parsing, obligation/debt/collateral |
test_builder.py |
Basic builder operations |
test_builder_advanced.py |
Complex builder scenarios |
test_builder_semantic.py |
Move call argument values, TxResult, veSCA |
test_bug_fixes.py |
Regression tests for all 12 v0.2.1 bugs |
test_integration.py |
End-to-end integration tests |
test_functional_mainnet.py |
Mainnet functional tests |
- Use Ruff for linting and formatting (configured in
pyproject.toml) - Use type hints for all public functions and methods
- Write docstrings for public functions and classes
- Keep functions focused and small
Please use GitHub Issues to report bugs or request features. Include:
- Python version
- SDK version
- Steps to reproduce
- Expected vs actual behavior
Feel free to open an issue or contact us at dev@scallop.io