Skip to main content

miden_standards/note/
network_note.rs

1use miden_protocol::account::AccountId;
2use miden_protocol::note::{Note, NoteAttachments, NoteMetadata, NoteType};
3
4use crate::note::{NetworkAccountTarget, NetworkAccountTargetError, NoteExecutionHint};
5
6/// A wrapper around a [`Note`] that is guaranteed to target a network account via a
7/// [`NetworkAccountTarget`] attachment.
8///
9/// This represents a note that is specifically targeted at a single network account. In the future,
10/// other types of network notes may exist (e.g., SWAP notes that can be consumed by network
11/// accounts but are not targeted at a specific one).
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct AccountTargetNetworkNote {
14    note: Note,
15}
16
17impl AccountTargetNetworkNote {
18    /// Attempts to construct an [`AccountTargetNetworkNote`] from `note`.
19    ///
20    /// Returns an error if:
21    /// - the note is not [`NoteType::Public`].
22    /// - the note's attachment cannot be decoded as a [`NetworkAccountTarget`].
23    pub fn new(note: Note) -> Result<Self, NetworkAccountTargetError> {
24        // Network notes must be public.
25        if note.metadata().note_type() != NoteType::Public {
26            return Err(NetworkAccountTargetError::NoteNotPublic(note.metadata().note_type()));
27        }
28
29        // Validate that the attachment is a valid NetworkAccountTarget.
30        NetworkAccountTarget::try_from(note.attachments())?;
31
32        Ok(Self { note })
33    }
34
35    /// Consumes `self` and returns the underlying [`Note`].
36    pub fn into_note(self) -> Note {
37        self.note
38    }
39
40    /// Returns a reference to the underlying [`Note`].
41    pub fn as_note(&self) -> &Note {
42        &self.note
43    }
44
45    /// Returns the [`NoteMetadata`] of the underlying note.
46    pub fn metadata(&self) -> &NoteMetadata {
47        self.note.metadata()
48    }
49
50    /// Returns the target network [`AccountId`].
51    pub fn target_account_id(&self) -> AccountId {
52        self.target().target_id()
53    }
54
55    /// Returns the decoded [`NetworkAccountTarget`] attachment.
56    pub fn target(&self) -> NetworkAccountTarget {
57        NetworkAccountTarget::try_from(self.note.attachments())
58            .expect("AccountTargetNetworkNote guarantees valid NetworkAccountTarget attachment")
59    }
60
61    /// Returns the [`NoteExecutionHint`] from the decoded [`NetworkAccountTarget`] attachment.
62    pub fn execution_hint(&self) -> NoteExecutionHint {
63        self.target().execution_hint()
64    }
65
66    /// Returns the raw [`NoteAttachments`] from the note's attachments.
67    pub fn attachments(&self) -> &NoteAttachments {
68        self.note.attachments()
69    }
70
71    /// Returns the [`NoteType`] of the underlying note.
72    pub fn note_type(&self) -> NoteType {
73        self.metadata().note_type()
74    }
75}
76
77/// Convenience helpers for [`Note`]s that may target a network account.
78pub trait NetworkNoteExt {
79    /// Returns `true` if this note is public and its attachment decodes as a
80    /// [`NetworkAccountTarget`].
81    fn is_network_note(&self) -> bool;
82
83    /// Consumes `self` and returns an [`AccountTargetNetworkNote`], or an error if the attachment
84    /// is not a valid target.
85    fn into_account_target_network_note(
86        self,
87    ) -> Result<AccountTargetNetworkNote, NetworkAccountTargetError>;
88}
89
90impl NetworkNoteExt for Note {
91    fn is_network_note(&self) -> bool {
92        self.metadata().note_type() == NoteType::Public
93            && NetworkAccountTarget::try_from(self.attachments()).is_ok()
94    }
95
96    fn into_account_target_network_note(
97        self,
98    ) -> Result<AccountTargetNetworkNote, NetworkAccountTargetError> {
99        AccountTargetNetworkNote::new(self)
100    }
101}
102
103impl TryFrom<Note> for AccountTargetNetworkNote {
104    type Error = NetworkAccountTargetError;
105
106    fn try_from(note: Note) -> Result<Self, Self::Error> {
107        Self::new(note)
108    }
109}