1use alloc::vec::Vec;
2
3use miden_protocol::account::AccountId;
4use miden_protocol::asset::Asset;
5use miden_protocol::block::BlockNumber;
6use miden_protocol::crypto::rand::FeltRng;
7use miden_protocol::errors::NoteError;
8use miden_protocol::note::{
9 Note,
10 NoteAssets,
11 NoteAttachment,
12 NoteDetails,
13 NoteInputs,
14 NoteMetadata,
15 NoteRecipient,
16 NoteTag,
17 NoteType,
18};
19use miden_protocol::{Felt, Word};
20use utils::build_swap_tag;
21
22pub mod mint_inputs;
23pub mod utils;
24
25mod network_account_target;
26pub use network_account_target::{NetworkAccountTarget, NetworkAccountTargetError};
27
28mod well_known_note_attachment;
29pub use well_known_note_attachment::WellKnownNoteAttachment;
30
31mod well_known_note;
32pub use mint_inputs::MintNoteInputs;
33pub use well_known_note::{NoteConsumptionStatus, WellKnownNote};
34
35pub fn create_p2id_note<R: FeltRng>(
49 sender: AccountId,
50 target: AccountId,
51 assets: Vec<Asset>,
52 note_type: NoteType,
53 attachment: NoteAttachment,
54 rng: &mut R,
55) -> Result<Note, NoteError> {
56 let serial_num = rng.draw_word();
57 let recipient = utils::build_p2id_recipient(target, serial_num)?;
58
59 let tag = NoteTag::with_account_target(target);
60
61 let metadata = NoteMetadata::new(sender, note_type, tag).with_attachment(attachment);
62 let vault = NoteAssets::new(assets)?;
63
64 Ok(Note::new(vault, metadata, recipient))
65}
66
67pub fn create_p2ide_note<R: FeltRng>(
81 sender: AccountId,
82 target: AccountId,
83 assets: Vec<Asset>,
84 reclaim_height: Option<BlockNumber>,
85 timelock_height: Option<BlockNumber>,
86 note_type: NoteType,
87 attachment: NoteAttachment,
88 rng: &mut R,
89) -> Result<Note, NoteError> {
90 let serial_num = rng.draw_word();
91 let recipient =
92 utils::build_p2ide_recipient(target, reclaim_height, timelock_height, serial_num)?;
93 let tag = NoteTag::with_account_target(target);
94
95 let metadata = NoteMetadata::new(sender, note_type, tag).with_attachment(attachment);
96 let vault = NoteAssets::new(assets)?;
97
98 Ok(Note::new(vault, metadata, recipient))
99}
100
101pub fn create_swap_note<R: FeltRng>(
111 sender: AccountId,
112 offered_asset: Asset,
113 requested_asset: Asset,
114 swap_note_type: NoteType,
115 swap_note_attachment: NoteAttachment,
116 payback_note_type: NoteType,
117 payback_note_attachment: NoteAttachment,
118 rng: &mut R,
119) -> Result<(Note, NoteDetails), NoteError> {
120 if requested_asset == offered_asset {
121 return Err(NoteError::other("requested asset same as offered asset"));
122 }
123
124 let note_script = WellKnownNote::SWAP.script();
125
126 let payback_serial_num = rng.draw_word();
127 let payback_recipient = utils::build_p2id_recipient(sender, payback_serial_num)?;
128
129 let requested_asset_word: Word = requested_asset.into();
130 let payback_tag = NoteTag::with_account_target(sender);
131
132 let attachment_scheme = Felt::from(payback_note_attachment.attachment_scheme().as_u32());
133 let attachment_kind = Felt::from(payback_note_attachment.attachment_kind().as_u8());
134 let attachment = payback_note_attachment.content().to_word();
135
136 let mut inputs = Vec::with_capacity(16);
137 inputs.extend_from_slice(&[
138 payback_note_type.into(),
139 payback_tag.into(),
140 attachment_scheme,
141 attachment_kind,
142 ]);
143 inputs.extend_from_slice(attachment.as_elements());
144 inputs.extend_from_slice(requested_asset_word.as_elements());
145 inputs.extend_from_slice(payback_recipient.digest().as_elements());
146 let inputs = NoteInputs::new(inputs)?;
147
148 let tag = build_swap_tag(swap_note_type, &offered_asset, &requested_asset);
150 let serial_num = rng.draw_word();
151
152 let metadata =
154 NoteMetadata::new(sender, swap_note_type, tag).with_attachment(swap_note_attachment);
155 let assets = NoteAssets::new(vec![offered_asset])?;
156 let recipient = NoteRecipient::new(serial_num, note_script, inputs);
157 let note = Note::new(assets, metadata, recipient);
158
159 let payback_assets = NoteAssets::new(vec![requested_asset])?;
161 let payback_note = NoteDetails::new(payback_assets, payback_recipient);
162
163 Ok((note, payback_note))
164}
165
166pub fn create_mint_note<R: FeltRng>(
189 faucet_id: AccountId,
190 sender: AccountId,
191 mint_inputs: MintNoteInputs,
192 attachment: NoteAttachment,
193 rng: &mut R,
194) -> Result<Note, NoteError> {
195 let note_script = WellKnownNote::MINT.script();
196 let serial_num = rng.draw_word();
197
198 let note_type = NoteType::Public;
200
201 let inputs = NoteInputs::from(mint_inputs);
203
204 let tag = NoteTag::with_account_target(faucet_id);
205
206 let metadata = NoteMetadata::new(sender, note_type, tag).with_attachment(attachment);
207 let assets = NoteAssets::new(vec![])?; let recipient = NoteRecipient::new(serial_num, note_script, inputs);
209
210 Ok(Note::new(assets, metadata, recipient))
211}
212
213pub fn create_burn_note<R: FeltRng>(
235 sender: AccountId,
236 faucet_id: AccountId,
237 fungible_asset: Asset,
238 attachment: NoteAttachment,
239 rng: &mut R,
240) -> Result<Note, NoteError> {
241 let note_script = WellKnownNote::BURN.script();
242 let serial_num = rng.draw_word();
243
244 let note_type = NoteType::Public;
246
247 let inputs = NoteInputs::new(vec![])?;
248 let tag = NoteTag::with_account_target(faucet_id);
249
250 let metadata = NoteMetadata::new(sender, note_type, tag).with_attachment(attachment);
251 let assets = NoteAssets::new(vec![fungible_asset])?; let recipient = NoteRecipient::new(serial_num, note_script, inputs);
253
254 Ok(Note::new(assets, metadata, recipient))
255}