Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Documents/Task Bounty/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Complete API reference for TaskBounty smart contracts.
- [Events](#events)
- [Errors](#errors)
- [Data Structures](#data-structures)
- [Task Metadata and Query Helpers](#task-metadata-and-query-helpers)

---

Expand Down Expand Up @@ -858,4 +859,43 @@ resolver.resolveDispute(disputeId, true);

---

## Task Metadata and Query Helpers

### `updateTaskCategory`
```solidity
function updateTaskCategory(uint256 taskId, string calldata category) external
```

Update the category assigned to a task.

### `addTaskTag`
```solidity
function addTaskTag(uint256 taskId, string calldata tag) external
```

Add a custom tag to a task.

### `getAllTasks`
```solidity
function getAllTasks() external view returns (Task[] memory tasks)
```

Return every task in creation order.

### `getTasksByCategory`
```solidity
function getTasksByCategory(string calldata category) external view returns (Task[] memory tasks)
```

Return tasks whose category matches the provided value.

### `getTasksByTag`
```solidity
function getTasksByTag(string calldata tag) external view returns (Task[] memory tasks)
```

Return tasks that contain the provided tag.

---

For more examples, see the [README.md](README.md) and test files in `test/`.
2 changes: 1 addition & 1 deletion Documents/Task Bounty/src/dispute.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{Address, Env, String};
use soroban_sdk::{panic_with_error, Address, Env, String};
use crate::types::{Dispute, TaskStatus, SubmissionStatus, Error};
use crate::storage;
use crate::events;
Expand Down
2 changes: 1 addition & 1 deletion Documents/Task Bounty/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{Address, Env, String, Symbol, symbol_short};
use soroban_sdk::{symbol_short, Address, Env, String};
use crate::types::Task;

/// Emit TaskCreated event
Expand Down
37 changes: 36 additions & 1 deletion Documents/Task Bounty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
mod types;
mod storage;
mod task;
mod query;
mod submission;
mod dispute;
mod events;
Expand All @@ -23,7 +24,7 @@ mod events;
mod test;

use soroban_sdk::{contract, contractimpl, Address, Env, String, Vec};
use types::{Task, Submission, TaskStatus, SubmissionStatus};
use types::{Task, Submission, TaskStatus};

#[contract]
pub struct TaskBountyContract;
Expand Down Expand Up @@ -79,6 +80,20 @@ impl TaskBountyContract {
)
}

/// Update the category for an existing task.
pub fn update_task_category(env: Env, task_id: u64, poster: Address, category: String) {
poster.require_auth();

task::update_task_category(&env, task_id, poster, category);
}

/// Add a custom tag to an existing task.
pub fn add_task_tag(env: Env, task_id: u64, poster: Address, tag: String) {
poster.require_auth();

task::add_task_tag(&env, task_id, poster, tag);
}

/// Submit work for a task
///
/// # Arguments
Expand Down Expand Up @@ -178,6 +193,26 @@ impl TaskBountyContract {
storage::get_task(&env, task_id)
}

/// Get every task in creation order.
pub fn get_all_tasks(env: Env) -> Vec<Task> {
query::get_all_tasks(&env)
}

/// Filter tasks by category.
pub fn get_tasks_by_category(env: Env, category: String) -> Vec<Task> {
query::get_tasks_by_category(&env, category)
}

/// Filter tasks by custom tag.
pub fn get_tasks_by_tag(env: Env, tag: String) -> Vec<Task> {
query::get_tasks_by_tag(&env, tag)
}

/// Filter tasks by status.
pub fn get_tasks_by_status(env: Env, status: TaskStatus) -> Vec<Task> {
query::get_tasks_by_status(&env, status)
}

/// Get submission details
///
/// # Arguments
Expand Down
55 changes: 55 additions & 0 deletions Documents/Task Bounty/src/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::{storage, types::{Task, TaskStatus}};
use soroban_sdk::{Env, String, Vec};

fn all_tasks(env: &Env) -> Vec<Task> {
let count = storage::get_task_counter(env);
let mut tasks: Vec<Task> = Vec::new(env);

for task_id in 1..=count {
if storage::task_exists(env, task_id) {
tasks.push_back(storage::get_task(env, task_id));
}
}

tasks
}

pub fn get_all_tasks(env: &Env) -> Vec<Task> {
all_tasks(env)
}

pub fn get_tasks_by_category(env: &Env, category: String) -> Vec<Task> {
let mut results: Vec<Task> = Vec::new(env);

for task in all_tasks(env).iter() {
if task.category == category {
results.push_back(task.clone());
}
}

results
}

pub fn get_tasks_by_tag(env: &Env, tag: String) -> Vec<Task> {
let mut results: Vec<Task> = Vec::new(env);

for task in all_tasks(env).iter() {
if task.tags.contains(tag.clone()) {
results.push_back(task.clone());
}
}

results
}

pub fn get_tasks_by_status(env: &Env, status: TaskStatus) -> Vec<Task> {
let mut results: Vec<Task> = Vec::new(env);

for task in all_tasks(env).iter() {
if task.status == status {
results.push_back(task.clone());
}
}

results
}
28 changes: 14 additions & 14 deletions Documents/Task Bounty/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,81 +10,81 @@ const ADMIN: &str = "ADMIN";

// Task storage
pub fn get_task(env: &Env, task_id: u64) -> Task {
let key = (b"TASK", task_id);
let key = ("TASK", task_id);
env.storage().persistent().get(&key).unwrap()
}

pub fn set_task(env: &Env, task: &Task) {
let key = (b"TASK", task.id);
let key = ("TASK", task.id);
env.storage().persistent().set(&key, task);
}

pub fn task_exists(env: &Env, task_id: u64) -> bool {
let key = (b"TASK", task_id);
let key = ("TASK", task_id);
env.storage().persistent().has(&key)
}

// Submission storage
pub fn get_submission(env: &Env, submission_id: u64) -> Submission {
let key = (b"SUB", submission_id);
let key = ("SUB", submission_id);
env.storage().persistent().get(&key).unwrap()
}

pub fn set_submission(env: &Env, submission: &Submission) {
let key = (b"SUB", submission.id);
let key = ("SUB", submission.id);
env.storage().persistent().set(&key, submission);
}

pub fn submission_exists(env: &Env, submission_id: u64) -> bool {
let key = (b"SUB", submission_id);
let key = ("SUB", submission_id);
env.storage().persistent().has(&key)
}

// Task submissions mapping
pub fn get_task_submissions(env: &Env, task_id: u64) -> Vec<u64> {
let key = (b"TASK_SUBS", task_id);
let key = ("TASK_SUBS", task_id);
env.storage()
.persistent()
.get(&key)
.unwrap_or(Vec::new(env))
}

pub fn add_task_submission(env: &Env, task_id: u64, submission_id: u64) {
let key = (b"TASK_SUBS", task_id);
let key = ("TASK_SUBS", task_id);
let mut submissions = get_task_submissions(env, task_id);
submissions.push_back(submission_id);
env.storage().persistent().set(&key, &submissions);
}

// Contributor submission tracking
pub fn has_contributor_submitted(env: &Env, task_id: u64, contributor: &Address) -> bool {
let key = (b"HAS_SUB", task_id, contributor);
let key = ("HAS_SUB", task_id, contributor);
env.storage().persistent().has(&key)
}

pub fn mark_contributor_submitted(env: &Env, task_id: u64, contributor: &Address) {
let key = (b"HAS_SUB", task_id, contributor);
let key = ("HAS_SUB", task_id, contributor);
env.storage().persistent().set(&key, &true);
}

// Dispute storage
pub fn get_dispute(env: &Env, dispute_id: u64) -> Dispute {
let key = (b"DISP", dispute_id);
let key = ("DISP", dispute_id);
env.storage().persistent().get(&key).unwrap()
}

pub fn set_dispute(env: &Env, dispute: &Dispute) {
let key = (b"DISP", dispute.id);
let key = ("DISP", dispute.id);
env.storage().persistent().set(&key, dispute);
}

pub fn has_active_dispute(env: &Env, task_id: u64, submission_id: u64) -> bool {
let key = (b"DISP_ACT", task_id, submission_id);
let key = ("DISP_ACT", task_id, submission_id);
env.storage().persistent().has(&key)
}

pub fn set_active_dispute(env: &Env, task_id: u64, submission_id: u64, dispute_id: u64) {
let key = (b"DISP_ACT", task_id, submission_id);
let key = ("DISP_ACT", task_id, submission_id);
env.storage().persistent().set(&key, &dispute_id);
}

Expand Down
2 changes: 1 addition & 1 deletion Documents/Task Bounty/src/submission.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{Address, Env, String, token};
use soroban_sdk::{panic_with_error, token, Address, Env, String};
use crate::types::{Submission, SubmissionStatus, TaskStatus, Error};
use crate::storage;
use crate::events;
Expand Down
36 changes: 35 additions & 1 deletion Documents/Task Bounty/src/task.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{Address, Env, String, token};
use soroban_sdk::{panic_with_error, token, Address, Env, String, Vec};
use crate::types::{Task, TaskStatus, Error};
use crate::storage;
use crate::events;
Expand Down Expand Up @@ -47,6 +47,8 @@ pub fn create_task(
poster: poster.clone(),
title: title.clone(),
description,
category: String::from_str(env, "General"),
tags: Vec::new(env),
token,
reward,
deadline,
Expand Down Expand Up @@ -105,3 +107,35 @@ pub fn cancel_task(env: &Env, task_id: u64, poster: Address) {
// Emit event
events::emit_task_cancelled(env, task_id, &poster);
}

pub fn update_task_category(env: &Env, task_id: u64, poster: Address, category: String) {
if !storage::task_exists(env, task_id) {
panic_with_error!(env, Error::TaskNotFound);
}

let mut task = storage::get_task(env, task_id);

if task.poster != poster {
panic_with_error!(env, Error::Unauthorized);
}

task.category = category;
storage::set_task(env, &task);
}

pub fn add_task_tag(env: &Env, task_id: u64, poster: Address, tag: String) {
if !storage::task_exists(env, task_id) {
panic_with_error!(env, Error::TaskNotFound);
}

let mut task = storage::get_task(env, task_id);

if task.poster != poster {
panic_with_error!(env, Error::Unauthorized);
}

if !task.tags.contains(tag.clone()) {
task.tags.push_back(tag);
storage::set_task(env, &task);
}
}
Loading