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