Hey there! π Thanks for wanting to contribute to Hunty. We're excited to have you on board! This guide will help you get started and make your first contribution smooth and enjoyable.
Before diving in, let's make sure you have everything you need to get started. Don't worry if you're new to Soroban or Rust - we've all been there, and we're here to help!
- Rust - We're using the latest stable version, so make sure yours is up to date
- Stellar CLI - You'll need the
stellarcommand installed for building contracts - Git - For version control (you probably already have this!)
- Basic Soroban knowledge - Don't worry if you're still learning! We have good first issues that are perfect for getting your feet wet
Let's get your development environment set up. It's pretty straightforward:
-
Clone the repo:
git clone https://github.com/Samuel1-ona/Hunty-contract.git cd Hunty-contract -
Build everything: This will compile all three contracts. Grab a coffee β - first builds can take a minute!
cd contracts/hunty-core && make build cd ../reward-manager && make build cd ../nft-reward && make build
-
Run the tests: Make sure everything works before you start making changes:
cd contracts/hunty-core && make test cd ../reward-manager && make test cd ../nft-reward && make test
If all the tests pass, you're good to go! π
Here's how we've organized things. Don't worry about memorizing this - you'll get familiar with it as you work:
hunty-contract/
βββ contracts/
β βββ hunty-core/ # This is where the main game logic lives
β β βββ src/
β β β βββ lib.rs # The heart of the contract - main functions here
β β β βββ types.rs # All our data structures (Hunt, Clue, etc.)
β β β βββ storage.rs # How we save and retrieve data
β β β βββ errors.rs # Custom error types for better error messages
β β β βββ test.rs # Tests go here - write lots of these!
β β βββ Cargo.toml
β βββ reward-manager/ # Handles all the reward distribution magic
β β βββ src/
β β β βββ lib.rs # Main reward coordination logic
β β β βββ xlm_handler.rs # XLM token distribution
β β β βββ nft_handler.rs # NFT minting coordination
β β β βββ test.rs
β β βββ Cargo.toml
β βββ nft-reward/ # Creates those cool NFT trophies
β βββ src/
β β βββ lib.rs
β β βββ test.rs
β βββ Cargo.toml
βββ Cargo.toml # Workspace config - don't touch this unless you know what you're doing
βββ README.md
Not sure where to start? That's totally fine! Here are some ways to find the perfect issue for you:
Head over to GitHub Issues and look for labels that match your experience level:
When opening a new issue, use the repository's bug report template for reproducible problems or feature request template for proposed improvements. Complete every relevant section so maintainers have enough context to respond.
- good first issue π’ - Perfect if you're new! These are designed to be approachable and help you learn the codebase
- enhancement π‘ - Adding new features or improving existing ones
- bug π΄ - Something's broken and needs fixing
- documentation π - Help us explain things better - great for writers!
- refactor π§ - Making code cleaner and more maintainable
If you're feeling overwhelmed, start with:
- Issues labeled "good first issue" - we specifically set these up for newcomers
- Documentation improvements - these are low-stress and help everyone
- Test coverage - writing tests is a great way to understand how things work
Here's the process we follow. It might seem like a lot at first, but it becomes second nature pretty quickly:
Always work on a branch - never commit directly to main! This keeps things organized and makes it easy to review your work.
git checkout -b feature/your-feature-name
# or for bug fixes:
git checkout -b fix/your-bug-fixPro tip: Make your branch name descriptive. feature/add-multi-answer-support is way better than feature/stuff!
Use feature/<short-description> for new capabilities and fix/<short-description> for bug fixes. Keep the description lowercase and hyphen-separated, and limit each branch to one focused change.
This is the fun part! A few things to keep in mind:
- Follow existing patterns - Look at how similar code is written in the project
- Write tests - Seriously, write tests. Your future self (and code reviewers) will thank you
- Update docs - If you're adding a new feature, make sure the docs reflect it
- Keep it simple - The best code is code that's easy to understand
Before you commit, make sure everything still works:
make testIf tests fail, don't panic! Read the error messages - they're usually pretty helpful. And if you're stuck, ask for help. We've all been there.
Write a clear commit message that explains what you did and why:
git add .
git commit -m "Add support for multiple valid answers per clue
This allows hunt creators to accept variations like 'Paris' or 'paris'
as correct answers, making the system more user-friendly."Good commit messages:
- Explain what changed
- Explain why (if it's not obvious)
- Are written in present tense ("Add feature" not "Added feature")
Once you're happy with your changes:
git push origin feature/your-feature-nameThen open a pull request against Samuel1-ona/hunty (usually into main). Prefer the GitHub CLI:
gh pr create --base main --title "your title" --body "Closes #<issue-number>"You can also create the PR from the GitHub UI after pushing. In your PR description, tell us:
- What you changed
- Why you changed it
- How to test it
- Any questions or concerns you have
GitHub will prefill the repository's pull request template. Complete its checklist to confirm that typechecking, linting, and the relevant tests were run before requesting review.
Use a concise, action-oriented PR title. In the description, explain why the change is needed, summarize the main changes, link the related issue, provide verification steps, and include screenshots for visual changes.
One-off repository administration scripts live under scripts/maintenance/. They are not part of the app build and are kept only for maintainers who need historical setup tooling.
| Script | Purpose |
|---|---|
assign_labels.sh |
Create common labels and apply them to matching issues by title |
create_issues.sh |
Batch-create GitHub issues from a predefined list |
create_issues_100.sh |
Bulk variant that creates many issues at once |
create_issues_safe.sh |
Safer issue-creation variant with rate-limiting |
create_mobile_issues.py |
Create mobile-specific GitHub issues |
See scripts/maintenance/README.md for details. Contributors fixing application code do not need to run these scripts.
To assign labels with the consolidated helper:
./scripts/maintenance/assign_labels.shRequires an authenticated gh CLI session and jq.
If you are changing the Soroban smart contracts, use the following workflow in addition to the general guidance above.
- Install the Stellar CLI and Soroban tools.
- Start a local sandbox for contract development:
stellar sandbox start
- Use the sandbox network for local deployment and testing before touching testnet or mainnet.
Run tests from the contract workspace before submitting changes:
stellar contract testIf you are working inside a specific contract package, run the tests there first and then from the workspace root.
- Create or select a funded testnet account.
- Deploy the updated contracts to testnet:
stellar contract deploy --network testnet --source-account <account>
- Record the deployed contract IDs and update the relevant environment variables in the app.
After redeploying contracts, update the environment values used by the web app:
NEXT_PUBLIC_HUNTY_CORE_ADDRESSNEXT_PUBLIC_REWARD_MANAGER_ADDRESSNEXT_PUBLIC_NFT_REWARD_ADDRESS
Redeploy the app so the frontend uses the new contract addresses.
Before opening a PR for contract work, confirm that you have:
- Reviewed the contract logic for correctness and security
- Run contract unit tests and captured the result
- Checked gas usage and reviewed any cost regressions
- Documented any deployed addresses or migration steps
- Verified the frontend is updated to the new contract addresses when needed
We're not super strict, but consistency helps everyone. Here's what we prefer:
- Follow Rust conventions -
cargo fmtis your friend, use it! - Add comments - Especially for complex logic. we will appreciate it
- Descriptive names -
calculate_player_score()is better thancalc() - Keep functions focused - If a function does too many things, consider breaking it up
Run cargo fmt before committing - it'll format your code automatically. Easy win! β¨
We can't stress this enough: write tests. They're not just for catching bugs - they're also documentation that shows how your code is supposed to work.
- Happy paths - Does it work when everything goes right?
- Edge cases - What happens with empty inputs? Invalid data? Boundary conditions?
- Error conditions - Does it fail gracefully with helpful error messages?
- Integration - If you're calling other contracts, test that interaction
- Aim for >80% code coverage
- Test edge cases - these are where bugs hide
- Include integration tests for cross-contract calls
- Make tests readable - they should tell a story
You've written the code, written the tests, and everything passes. Awesome! Now let's get it reviewed:
- β All tests pass (locally and in CI)
- β Documentation is updated (if needed)
- β
Code is formatted (
cargo fmt) - β You've tested your changes manually (if applicable)
A good PR description helps reviewers understand your work quickly. Please note: Completion reports and implementation summaries belong in the PR description. Do not commit them to the repository as tracked documents.
## What This Does
Adds support for multiple valid answers per clue, allowing hunt creators
to accept variations like "Paris", "paris", or "City of Light" as correct.
## Why
Some clues have multiple valid answers, and we want to be flexible while
still maintaining security through hash verification.
## Testing
- Added unit tests for multi-answer verification
- Tested with various answer formats
- Verified backward compatibility with single-answer clues
## Related Issues
Closes #21Don't take feedback personally! Code reviews are about making the code better, not criticizing you. We're all learning and improving together.
Each contract has its own quirks. Here's what to know:
This is the main game logic, so it's pretty important:
- types.rs - Define all your data structures here. Keep them organized and well-documented
- storage.rs - Storage access patterns. Make sure keys are unique and consistent
- errors.rs - Custom errors make debugging way easier. Use them!
- lib.rs - Main contract logic. Keep functions focused and testable
This coordinates rewards, so precision matters:
- Coordinate with both XLM and NFT handlers - they need to work together
- Ensure atomic operations - either everything succeeds or nothing does
- Handle edge cases gracefully - what if a transfer fails? What if the pool is empty?
NFTs are cool, but they need to be done right:
- Follow Stellar NFT standards - this ensures compatibility
- Keep metadata consistent - it's what makes each NFT unique
- Track ownership properly - this is critical for transfers
The #1 recurring damage in this repo's history: conflict resolutions that keep both sides of a conflicting hunk. This silently duplicates routes, components, and config β 31 files were damaged this way. Don't be the next one.
-
Never accept both sides of a code block. If both sides define the same route, export, component, or config key, pick ONE (usually
main's version, unless your branch intentionally changes it). -
After resolving, verify no duplication slipped through:
# Routes: each API path should appear exactly once per method grep -rn "export const POST" apps/web/app/api --include="*.ts" | sort | uniq -d # Build must pass β a duplicated symbol will fail here pnpm build
-
Rebase on
mainbefore requesting review:git fetch origin git rebase origin/main # resolve any conflicts (same rules), then force-push your branch git push --force-with-lease -
Run the full local check after rebasing β a clean rebase is not enough if the merge kept both sides:
pnpm lint && pnpm test && pnpm build
A "kept both sides" resolution sometimes compiles fine (duplicate files do), but breaks behavior at runtime: two handlers for one route, double-mounted providers, or conflicting config values. The failure shows up far from the cause and costs everyone time.
Stuck on something? We've got your back:
- Leave a message on the issue - I will get back to you as quick as possible
By contributing to Hunty, you agree that your contributions will be licensed under the same license as the project. This basically means your code becomes part of the open source project.
Thanks for reading this far! We're genuinely excited to see what you'll build. Happy coding! π