solagent_plugin_gibwork/
lib.rs

1use base64::{engine::general_purpose, Engine};
2use serde::{Deserialize, Serialize};
3use solagent_core::{
4    solana_sdk::{
5        commitment_config::CommitmentConfig, pubkey::Pubkey, transaction::VersionedTransaction,
6    },
7    SolanaAgentKit,
8};
9
10#[derive(Serialize)]
11struct TaskRequest {
12    title: String,
13    content: String,
14    requirements: String,
15    tags: Vec<String>,
16    payer: String,
17    token: TokenInfo,
18}
19
20#[derive(Serialize)]
21struct TokenInfo {
22    #[serde(rename = "mintAddress")]
23    mint_address: String,
24    amount: u64,
25}
26
27#[derive(Deserialize)]
28struct TaskResponse {
29    #[serde(rename = "taskId")]
30    task_id: String,
31    #[serde(rename = "serializedTransaction")]
32    serialized_transaction: String,
33}
34
35#[derive(Debug, Serialize, Deserialize)]
36pub struct GibworkCreateTaskResponse {
37    pub status: String,
38    pub task_id: String,
39    pub signature: String,
40}
41
42/// Create a new task on Gibwork
43///
44/// # Arguments
45///
46/// * `agent` - SolanaAgentKit instance
47/// * `title` - Title of the task
48/// * `content` - Description of the task
49/// * `requirements` - Requirements to complete the task
50/// * `tags` - List of tags associated with the task
51/// * `token_mint_address` - Token mint address for payment
52/// * `token_amount` - Payment amount for the task
53/// * `payer` - Optional payer address (defaults to agent's wallet address)
54///
55/// # Returns
56///
57/// Object containing task creation transaction and generated taskId
58#[allow(clippy::too_many_arguments)]
59pub async fn create_gibwork_task(
60    agent: &SolanaAgentKit,
61    title: &str,
62    content: &str,
63    requirements: &str,
64    tags: Vec<String>,
65    token_mint_address: &str,
66    token_amount: u64,
67    payer: Option<Pubkey>,
68) -> Result<GibworkCreateTaskResponse, Box<dyn std::error::Error>> {
69    let request = TaskRequest {
70        title: title.to_string(),
71        content: content.to_string(),
72        requirements: requirements.to_string(),
73        tags,
74        payer: payer.unwrap_or(agent.wallet.pubkey).to_string(),
75        token: TokenInfo {
76            mint_address: token_mint_address.to_string(),
77            amount: token_amount,
78        },
79    };
80
81    // Send request to Gibwork API
82    let client = reqwest::Client::new();
83    let response = client
84        .post("https://api2.gib.work/tasks/public/transaction")
85        .json(&request)
86        .send()
87        .await?;
88
89    if !response.status().is_success() {
90        return Err(format!("API request failed: {}", response.status()).into());
91    }
92
93    let task_response: TaskResponse = response.json().await?;
94
95    // Deserialize and sign transaction
96    let transaction_data =
97        general_purpose::STANDARD.decode(task_response.serialized_transaction.as_str())?;
98
99    let mut versioned_transaction: VersionedTransaction = bincode::deserialize(&transaction_data)?;
100
101    // Get latest blockhash and sign transaction
102    let blockhash = agent.connection.get_latest_blockhash()?;
103    versioned_transaction
104        .message
105        .set_recent_blockhash(blockhash);
106    let signed_transaction =
107        VersionedTransaction::try_new(versioned_transaction.message, &[&agent.wallet.keypair])?;
108
109    // Send and confirm transaction
110    let signature = agent.connection.send_transaction(&signed_transaction)?;
111    agent.connection.confirm_transaction_with_spinner(
112        &signature,
113        &blockhash,
114        CommitmentConfig::confirmed(),
115    )?;
116
117    Ok(GibworkCreateTaskResponse {
118        status: "success".to_string(),
119        task_id: task_response.task_id,
120        signature: signature.to_string(),
121    })
122}