The source code as discussed and posted on the Tari Discord server, the latest (so far) running version bind to this bot:
// Import necessary libraries and dependencies
use tari_core::crypto::tari_utilities::hex::Hex;
use tari_crypto::ristretto::pedersen::PedersenCommitment;
use tari_utilities::message_format::MessageFormat;
use tari_utilities::ByteArray;
// Define the RewardSystem contract
pub struct RewardSystem {
tasks: HashMap
rewards: HashMap
tokens: HashMap
}
impl RewardSystem {
// Define the Task struct
pub struct Task {
topic: String,
description: String,
symbol: String,
timer: u64,
min_reward: u64,
initial_deposit: u64,
completion_candidates: HashMap
supporters: Vec
}
// Define the CompletionCandidate struct
pub struct CompletionCandidate {
proof_text: String,
proof_binary: Vec
wallet_address: String,
}
// Define the Supporter struct
pub struct Supporter {
supporter_id: u64,
task_id: u64,
reward: u64,
}
// Define the Reward struct
pub struct Reward {
task_id: u64,
supporter_id: u64,
reward: u64,
}
// Method to create a new task
pub fn create_task(
&mut self,
topic: String,
description: String,
symbol: String,
timer: u64,
min_reward: u64,
initial_deposit: u64,
) -> u64 {
// Generate a unique task ID
let task_id = self.tasks.len() as u64 + 1;
// Create a new task
let task = Task {
topic,
description,
symbol,
timer,
min_reward,
initial_deposit,
completion_candidates: HashMap::new(),
supporters: Vec::new(),
};
// Store the task in the tasks mapping
self.tasks.insert(task_id, task);
// Return the task ID
task_id
}
// Method to add a reward to a task
pub fn add_reward(&mut self, task_id: u64, reward: u64) {
// Check if the task exists
if let Some(task) = self.tasks.get_mut(&task_id) {
// Calculate the number of tokens to mint
let tokens_to_mint = reward / task.min_reward;
// Create a new reward
let new_reward = Reward {
task_id,
supporter_id: self.tokens.len() as u64 + 1,
reward,
};
// Store the reward in the rewards mapping
self.rewards.entry(task_id).or_insert(Vec::new()).push(new_reward);
// Mint tokens for the supporter
self.tokens.insert(new_reward.supporter_id, tokens_to_mint);
}
}
// Method for a candidate to claim task completion
pub fn task_completion_candidate(
&mut self,
task_id: u64,
proof_text: String,
proof_binary: Vec
wallet_address: String,
) {
// Check if the task exists
if let Some(task) = self.tasks.get_mut(&task_id) {
//
// Create a new completion candidate
let candidate = CompletionCandidate {
proof_text,
proof_binary,
wallet_address,
};
// Add the candidate to the task's completion candidates
task.completion_candidates.insert(candidate_id, candidate);
// Increment the candidate ID
let candidate_id = task.completion_candidates.len() as u64;
// Add the candidate to the task's completion candidates
task.completion_candidates.insert(candidate_id, candidate);
// Notify the candidate ID to the supporters
for supporter in &task.supporters {
println!(
"CandidateID {}: registered. Supporters may now vote to accept or reject.",
candidate_id
);
}
}
}
// Method for supporters to accept or reject a completion candidate
pub fn accept_candidate(&mut self, candidate_id: u64, supporter_id: u64, decision: bool) {
// Check if the candidate exists
for task in self.tasks.values_mut() {
if let Some(candidate) = task.completion_candidates.get_mut(&candidate_id) {
// Find the reward associated with the task and supporter
let reward = self
.rewards
.get(&task.task_id)
.and_then(|rewards| rewards.iter().find(|r| r.supporter_id == supporter_id))
.cloned();
match reward {
Some(reward) => {
// Check if the supporter has enough tokens
if let Some(tokens) = self.tokens.get_mut(&supporter_id) {
if *tokens >= reward.reward {
// Decrement the supporter's tokens
*tokens -= reward.reward;
// Check if the decision is to accept the candidate
if decision {
// Transfer the reward to the candidate
// (implementation not included for brevity)
println!(
"Candidate {}: Approved by supporter {}. Reward of {} sent to supporter {}. Remaining bounty: {}",
candidate_id,
supporter_id,
reward.reward,
supporter_id,
// remaining bounty value
);
} else {
println!(
"Candidate {}: Rejected by supporter {}. No reward sent. Remaining bounty: {}",
candidate_id,
supporter_id,
// remaining bounty value
);
}
}
}
}
None => {
println!("Reward not found for supporter {} and task ID {}", supporter_id, task.task_id);
}
}
}
}
}
// Method to list all open tasks
pub fn list_tasks(&self) {
for (task_id, task) in &self.tasks {
let supporters_count = task.supporters.len();
println!(
"TaskID: {}, Subject: {}, Total Value: {}, Supporters Count: {}",
task_id,
task.topic,
// total value
supporters_count,
);
}
}
}
Please note that the nostr interface is bind to this smart contract using TCL and run distributed on nostr, while the main Tari contract is obviously written in rust and depends on Tari toolchain to build.
Njoy