Skip to content

Latest commit

 

History

History
169 lines (127 loc) · 5.65 KB

CONTRIBUTING.md

File metadata and controls

169 lines (127 loc) · 5.65 KB

Contributing to Scallop Python SDK

Thank you for your interest in contributing to the Scallop Python SDK!

Getting Started

  1. Fork the repository
  2. Clone your fork:
    git clone https://github.com/YOUR_USERNAME/sui-scallop-sdk-python.git
    cd sui-scallop-sdk-python
  3. Install development dependencies:
    pip install -e ".[dev]"
  4. Install pre-commit hooks:
    pre-commit install

Development Workflow

Running Tests

make test
# or
pytest tests/ -v

Linting & Formatting

# Check lint
make lint

# Auto-format
make format

# Run all checks (lint + typecheck + test)
make all

Type Checking

make typecheck
# or
mypy src/sui_scallop_sdk

Commit Convention

This 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.

Pull Request Process

  1. Create a new branch for your feature/fix
  2. Make your changes
  3. Ensure all checks pass: make all
  4. Update CHANGELOG.md if the change is user-facing
  5. Submit a pull request using the PR template

Testing SOP

This section codifies lessons learned from the v0.2.1 audit, where 12 bugs (5 critical) went undetected by the existing test suite.

Testing Principles

  1. 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
  2. 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.
  3. Mock external dependencies, not logic: Use unittest.mock.patch for RPC calls, HTTP requests, and Oracle APIs. Never mock the unit under test.

  4. Regression tests for every bug fix: Each resolved bug must have a dedicated regression test that would fail if the bug were reintroduced.

Test Categories (required for each module)

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

Writing Tests Checklist

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, never lstrip/rstrip for 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

Running Tests with Coverage

# 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 Organization

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

Code Style

  • 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

Reporting Issues

Please use GitHub Issues to report bugs or request features. Include:

  • Python version
  • SDK version
  • Steps to reproduce
  • Expected vs actual behavior

Questions?

Feel free to open an issue or contact us at dev@scallop.io