clockwork_http/instructions/
request_new.rs

1use {
2    crate::state::{
3        Api, Config, HttpMethod, Request, RequestAccount, SEED_API, SEED_CONFIG, SEED_REQUEST,
4    },
5    anchor_lang::{
6        prelude::*,
7        solana_program::system_program,
8        system_program::{transfer, Transfer},
9    },
10    clockwork_pool::state::Pool,
11    std::{collections::HashMap, mem::size_of},
12};
13
14#[derive(Accounts)]
15#[instruction(
16    id: String, 
17    method: HttpMethod, 
18    route: String
19)]
20pub struct RequestNew<'info> {
21    #[account(
22        seeds = [
23            SEED_API,
24            api.authority.as_ref(),
25            api.base_url.as_bytes().as_ref(),
26        ],
27        bump,
28    )]
29    pub api: Account<'info, Api>,
30
31    #[account()]
32    pub caller: Signer<'info>,
33
34    #[account(seeds = [SEED_CONFIG], bump)]
35    pub config: Account<'info, Config>,
36
37    #[account(mut)]
38    pub payer: Signer<'info>,
39
40    #[account()]
41    pub pool: Account<'info, Pool>,
42
43    #[account(
44        init,
45        seeds = [
46            SEED_REQUEST,
47            api.key().as_ref(),
48            caller.key().as_ref(),
49            id.as_bytes().as_ref(),
50        ],
51        bump,
52        space = 8 + size_of::<Request>(),
53        payer = payer
54    )]
55    pub request: Account<'info, Request>,
56
57    #[account(address = system_program::ID)]
58    pub system_program: Program<'info, System>,
59}
60
61pub fn handler<'info>(
62    ctx: Context<RequestNew>,
63    id: String,
64    method: HttpMethod,
65    route: String,
66) -> Result<()> {
67    // Fetch accounts
68    let api = &ctx.accounts.api;
69    let caller = &ctx.accounts.caller;
70    let config = &ctx.accounts.config;
71    let payer = &mut ctx.accounts.payer;
72    let pool = &ctx.accounts.pool;
73    let request = &mut ctx.accounts.request;
74    let system_program = &ctx.accounts.system_program;
75
76    // TODO Validate route is a relative path
77
78    // Initialize the request account
79    let current_slot = Clock::get().unwrap().slot;
80    let fee_amount = config.request_fee;
81    let headers = HashMap::new(); // TODO Get headers from ix data
82    let workers = pool
83        .clone()
84        .into_inner()
85        .workers
86        .iter()
87        .map(|k| *k)
88        .collect::<Vec<Pubkey>>();
89    request.new(
90        api,
91        caller.key(),
92        current_slot,
93        fee_amount,
94        headers,
95        id,
96        method,
97        route,
98        workers,
99    )?;
100
101    // Transfer fees into request account to hold in escrow
102    transfer(
103        CpiContext::new(
104            system_program.to_account_info(),
105            Transfer {
106                from: payer.to_account_info(),
107                to: request.to_account_info(),
108            },
109        ),
110        fee_amount,
111    )?;
112
113    Ok(())
114}