1use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use serde_repr::Serialize_repr;
6use solana_program::instruction::Instruction;
7
8#[derive(Serialize_repr)]
12#[repr(u8)]
13pub enum AccountRole {
14 WritableSigner = 0b11,
15 ReadonlySigner = 0b10,
16 Writable = 0b01,
17 Readonly = 0b00,
18}
19
20#[derive(Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct Input {
24 pub poa_name: String,
26 pub proposal_storage_key: String,
27}
28
29#[derive(Serialize)]
31#[serde(rename_all = "camelCase")]
32pub struct AccountMeta {
33 pub address: String,
34 pub role: AccountRole,
35}
36
37#[derive(Serialize)]
39#[serde(rename_all = "camelCase")]
40pub struct ProposalInstruction {
41 pub program_address: String,
42 pub accounts: Vec<AccountMeta>,
43 pub data: Vec<u8>,
44}
45
46#[derive(Serialize)]
48#[serde(rename_all = "camelCase")]
49pub struct Response {
50 pub proposal_instructions: Vec<ProposalInstruction>,
52}
53
54impl Response {
55 pub fn to_output_ix(&self) -> Result<String> {
59 Ok(serde_json::to_string_pretty(&self)?)
60 }
61}
62
63impl From<Instruction> for ProposalInstruction {
64 fn from(value: Instruction) -> Self {
65 ProposalInstruction {
66 program_address: value.program_id.to_string(),
67 accounts: value
68 .accounts
69 .into_iter()
70 .map(|meta| AccountMeta {
71 address: meta.pubkey.to_string(),
72 role: (meta.is_writable, meta.is_signer).into(),
73 })
74 .collect(),
75 data: value.data,
76 }
77 }
78}
79
80impl From<&Instruction> for ProposalInstruction {
81 fn from(value: &Instruction) -> Self {
82 ProposalInstruction {
83 program_address: value.program_id.to_string(),
84 accounts: value
85 .accounts
86 .iter()
87 .map(|meta| AccountMeta {
88 address: meta.pubkey.to_string(),
89 role: (meta.is_writable, meta.is_signer).into(),
90 })
91 .collect(),
92 data: value.data.clone(),
93 }
94 }
95}
96
97impl From<&[Instruction]> for Response {
98 fn from(value: &[Instruction]) -> Self {
99 Response {
100 proposal_instructions: value.iter().map(Into::into).collect(),
101 }
102 }
103}
104
105impl From<Instruction> for Response {
106 fn from(value: Instruction) -> Self {
107 Response {
108 proposal_instructions: vec![value.into()],
109 }
110 }
111}
112
113impl From<&Instruction> for Response {
114 fn from(value: &Instruction) -> Self {
115 Response {
116 proposal_instructions: vec![value.into()],
117 }
118 }
119}
120
121impl From<Vec<Instruction>> for Response {
122 fn from(value: Vec<Instruction>) -> Self {
123 Response {
124 proposal_instructions: value.into_iter().map(Into::into).collect(),
125 }
126 }
127}
128
129
130impl From<(bool, bool)> for AccountRole {
131 fn from((is_writable, is_signer): (bool, bool)) -> Self {
132 match (is_writable, is_signer) {
133 (false, false) => AccountRole::Readonly,
134 (false, true) => AccountRole::ReadonlySigner,
135 (true, false) => AccountRole::Writable,
136 (true, true) => AccountRole::WritableSigner,
137 }
138 }
139}