tari_template_lib/models/
proof.rs1use std::collections::BTreeSet;
24
25use serde::{Deserialize, Serialize};
26use tari_bor::BorTag;
27use tari_template_abi::{call_engine, rust::fmt, EngineOp};
28
29use crate::{
30 args::{InvokeResult, ProofAction, ProofInvokeArg, ProofRef},
31 models::{BinaryTag, NonFungibleId, ResourceAddress},
32 prelude::ResourceType,
33 types::Amount,
34};
35
36const TAG: u64 = BinaryTag::ProofId.as_u64();
37
38#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd, Hash)]
40#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))]
41pub struct ProofId(BorTag<u32, TAG>);
42
43impl From<u32> for ProofId {
44 fn from(value: u32) -> Self {
45 Self(BorTag::new(value))
46 }
47}
48
49impl fmt::Display for ProofId {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "ProofId({})", self.0.inner())
52 }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
58#[serde(transparent)]
59pub struct Proof {
60 id: ProofId,
61}
62
63impl Proof {
64 pub const fn from_id(id: ProofId) -> Self {
65 Self { id }
66 }
67
68 pub fn id(&self) -> ProofId {
69 self.id
70 }
71
72 pub fn resource_address(&self) -> ResourceAddress {
73 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
74 proof_ref: ProofRef::Ref(self.id),
75 action: ProofAction::GetResourceAddress,
76 args: invoke_args![],
77 });
78
79 resp.decode()
80 .expect("Proof GetResourceAddress returned invalid resource address")
81 }
82
83 pub fn resource_type(&self) -> ResourceType {
84 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
85 proof_ref: ProofRef::Ref(self.id),
86 action: ProofAction::GetResourceType,
87 args: invoke_args![],
88 });
89
90 resp.decode()
91 .expect("Proof GetResourceType returned invalid resource type")
92 }
93
94 pub fn get_non_fungibles(&self) -> BTreeSet<NonFungibleId> {
95 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
96 proof_ref: ProofRef::Ref(self.id),
97 action: ProofAction::GetNonFungibles,
98 args: invoke_args![],
99 });
100
101 resp.decode()
102 .expect("Proof GetNonFungibles returned invalid non-fungibles")
103 }
104
105 pub fn amount(&self) -> Amount {
106 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
107 proof_ref: ProofRef::Ref(self.id),
108 action: ProofAction::GetAmount,
109 args: invoke_args![],
110 });
111
112 resp.decode().expect("Proof GetAmount returned invalid amount")
113 }
114
115 #[must_use = "ProofAccess must used"]
116 pub fn authorize(&self) -> ProofAccess {
117 self.try_authorize().expect("Proof authorization failed")
118 }
119
120 pub fn authorize_with<F: FnOnce() -> R, R>(&self, f: F) -> R {
121 let _auth = self.try_authorize().expect("Proof authorization failed");
122 f()
123 }
124
125 pub fn try_authorize(&self) -> Result<ProofAccess, NotAuthorized> {
127 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
128 proof_ref: ProofRef::Ref(self.id),
129 action: ProofAction::Authorize,
130 args: invoke_args![],
131 });
132
133 resp.decode::<Result<(), NotAuthorized>>()
134 .expect("Proof Access error")?;
135 Ok(ProofAccess { id: self.id })
136 }
137
138 pub fn drop(self) {
140 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
141 proof_ref: ProofRef::Ref(self.id),
142 action: ProofAction::Drop,
143 args: invoke_args![],
144 });
145
146 resp.decode().expect("Proof drop error")
147 }
148
149 pub fn assert_resource(&self, resource_address: ResourceAddress) {
150 assert_eq!(
151 self.resource_address(),
152 resource_address,
153 "Proof of resource did not match {resource_address}"
154 );
155 }
156}
157
158#[derive(Debug, Serialize, Deserialize)]
160pub struct NotAuthorized;
161
162#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct ProofAccess {
165 pub id: ProofId,
166}
167
168impl Drop for ProofAccess {
169 fn drop(&mut self) {
170 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
171 proof_ref: ProofRef::Ref(self.id),
172 action: ProofAction::DropAuthorize,
173 args: invoke_args![],
174 });
175
176 resp.decode::<()>()
177 .unwrap_or_else(|_| panic!("Drop failed for proof {}", self.id));
178 }
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct ProofAuth {
185 pub id: ProofId,
186}
187
188impl Drop for ProofAuth {
189 fn drop(&mut self) {
190 let resp: InvokeResult = call_engine(EngineOp::ProofInvoke, &ProofInvokeArg {
191 proof_ref: ProofRef::Ref(self.id),
192 action: ProofAction::Drop,
193 args: invoke_args![],
194 });
195
196 resp.decode::<()>()
197 .unwrap_or_else(|_| panic!("Drop failed for proof {}", self.id));
198 }
199}