winterwallet_client/
plan.rs1use solana_address::Address;
2use solana_instruction::{AccountMeta, Instruction};
3use winterwallet_common::SIGNATURE_LEN;
4
5use crate::{
6 AdvancePayload, Error, advance, advance_preimage, close, encode_advance,
7 transaction::{
8 DEFAULT_ADVANCE_COMPUTE_UNIT_LIMIT, estimate_legacy_transaction_size,
9 validate_legacy_transaction_size, with_compute_budget,
10 },
11 withdraw,
12};
13
14pub struct AdvancePlan {
19 wallet_pda: Address,
20 new_root: [u8; 32],
21 payload: AdvancePayload,
22 account_addresses: Vec<[u8; 32]>,
23}
24
25impl AdvancePlan {
26 pub fn new(
28 wallet_pda: &Address,
29 new_root: &[u8; 32],
30 inner_instructions: &[Instruction],
31 ) -> Result<Self, Error> {
32 let payload = encode_advance(inner_instructions)?;
33 let account_addresses = payload
34 .accounts
35 .iter()
36 .map(|meta| *meta.pubkey.as_array())
37 .collect();
38
39 Ok(Self {
40 wallet_pda: *wallet_pda,
41 new_root: *new_root,
42 payload,
43 account_addresses,
44 })
45 }
46
47 pub fn wallet_pda(&self) -> &Address {
49 &self.wallet_pda
50 }
51
52 pub fn withdraw(
54 wallet_pda: &Address,
55 receiver: &Address,
56 lamports: u64,
57 new_root: &[u8; 32],
58 ) -> Result<Self, Error> {
59 Self::new(
60 wallet_pda,
61 new_root,
62 &[withdraw(wallet_pda, receiver, lamports)],
63 )
64 }
65
66 pub fn close(
69 wallet_pda: &Address,
70 receiver: &Address,
71 new_root: &[u8; 32],
72 ) -> Result<Self, Error> {
73 Self::new(wallet_pda, new_root, &[close(wallet_pda, receiver)])
74 }
75
76 pub fn payload(&self) -> &[u8] {
78 &self.payload.data
79 }
80
81 pub fn passthrough_accounts(&self) -> &[AccountMeta] {
83 &self.payload.accounts
84 }
85
86 pub fn account_addresses(&self) -> &[[u8; 32]] {
88 &self.account_addresses
89 }
90
91 pub fn new_root(&self) -> &[u8; 32] {
93 &self.new_root
94 }
95
96 pub fn preimage<'a>(
98 &'a self,
99 wallet_id: &'a [u8; 32],
100 current_root: &'a [u8; 32],
101 ) -> Vec<&'a [u8]> {
102 advance_preimage(
103 wallet_id,
104 current_root,
105 &self.new_root,
106 &self.account_addresses,
107 &self.payload.data,
108 )
109 }
110
111 pub fn instruction(&self, signature_bytes: &[u8; SIGNATURE_LEN]) -> Instruction {
113 advance(
114 &self.wallet_pda,
115 &self.payload.accounts,
116 signature_bytes,
117 &self.new_root,
118 &self.payload.data,
119 )
120 }
121
122 pub fn estimate_transaction_size(
124 &self,
125 payer: &Address,
126 signature_bytes: &[u8; SIGNATURE_LEN],
127 ) -> Result<usize, Error> {
128 let ix = self.instruction(signature_bytes);
129 let ixs = with_compute_budget(&[ix], DEFAULT_ADVANCE_COMPUTE_UNIT_LIMIT, 0);
130 estimate_legacy_transaction_size(payer, &ixs)
131 }
132
133 pub fn validate_transaction_size(
135 &self,
136 payer: &Address,
137 signature_bytes: &[u8; SIGNATURE_LEN],
138 ) -> Result<usize, Error> {
139 let ix = self.instruction(signature_bytes);
140 let ixs = with_compute_budget(&[ix], DEFAULT_ADVANCE_COMPUTE_UNIT_LIMIT, 0);
141 validate_legacy_transaction_size(payer, &ixs)
142 }
143}