kaspa_consensus_client/
outpoint.rs1#![allow(non_snake_case)]
6
7use cfg_if::cfg_if;
8
9use crate::imports::*;
10use crate::result::Result;
11
12#[wasm_bindgen(typescript_custom_section)]
13const TS_TRANSACTION_OUTPOINT: &'static str = r#"
14/**
15 * Interface defines the structure of a transaction outpoint (used by transaction input).
16 *
17 * @category Consensus
18 */
19export interface ITransactionOutpoint {
20 transactionId: HexString;
21 index: number;
22}
23"#;
24
25#[wasm_bindgen]
26extern "C" {
27 #[wasm_bindgen(typescript_type = "ITransactionOutpoint | TransactionOutpoint")]
30 pub type TransactionOutpointT;
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Ord, PartialOrd)]
35#[serde(rename_all = "camelCase")]
36pub struct TransactionOutpointInner {
37 pub transaction_id: TransactionId,
38 pub index: TransactionIndexType,
39}
40
41impl std::fmt::Display for TransactionOutpointInner {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(f, "{}-{}", self.transaction_id, self.index)
44 }
45}
46
47impl TransactionOutpointInner {
48 pub fn new(transaction_id: TransactionId, index: TransactionIndexType) -> Self {
49 Self { transaction_id, index }
50 }
51
52 pub fn to_bytes(&self) -> Vec<u8> {
53 let mut data = self.transaction_id.as_bytes().to_vec();
54 data.extend(self.index.to_be_bytes());
55 data
56 }
57}
58
59impl From<cctx::TransactionOutpoint> for TransactionOutpointInner {
60 fn from(outpoint: cctx::TransactionOutpoint) -> Self {
61 TransactionOutpointInner { transaction_id: outpoint.transaction_id, index: outpoint.index }
62 }
63}
64
65impl TryFrom<&JsValue> for TransactionOutpointInner {
66 type Error = Error;
67 fn try_from(js_value: &JsValue) -> Result<Self, Self::Error> {
68 if let Some(string) = js_value.as_string() {
69 let vec = string.split('-').collect::<Vec<_>>();
70 if vec.len() == 2 {
71 let transaction_id: TransactionId = vec[0].parse()?;
72 let id: u32 = vec[1].parse()?;
73 Ok(TransactionOutpointInner::new(transaction_id, id))
74 } else {
75 Err(Error::InvalidTransactionOutpoint(string))
76 }
77 } else if let Some(object) = js_sys::Object::try_from(js_value) {
78 let transaction_id: TransactionId = object.get_value("transactionId")?.try_into_owned()?;
79 let index = object.get_u32("index")?;
80 Ok(TransactionOutpointInner::new(transaction_id, index))
81 } else {
82 Err("outpoint is not an object".into())
83 }
84 }
85}
86
87#[derive(Clone, Debug, Serialize, Deserialize, CastFromJs)]
93#[serde(rename_all = "camelCase")]
94#[wasm_bindgen(inspectable)]
95pub struct TransactionOutpoint {
96 inner: Arc<TransactionOutpointInner>,
97}
98
99impl TransactionOutpoint {
100 pub fn new(transaction_id: TransactionId, index: u32) -> TransactionOutpoint {
101 Self { inner: Arc::new(TransactionOutpointInner { transaction_id, index }) }
102 }
103
104 #[inline(always)]
105 pub fn inner(&self) -> &TransactionOutpointInner {
106 &self.inner
107 }
108
109 #[inline(always)]
110 pub fn transaction_id(&self) -> TransactionId {
111 self.inner().transaction_id
112 }
113
114 #[inline(always)]
115 pub fn index(&self) -> TransactionIndexType {
116 self.inner().index
117 }
118
119 #[inline(always)]
120 pub fn transaction_id_as_ref(&self) -> &TransactionId {
121 &self.inner().transaction_id
122 }
123
124 #[inline(always)]
125 pub fn id(&self) -> &TransactionOutpointInner {
126 self.inner()
127 }
128}
129
130cfg_if! {
131 if #[cfg(feature = "wasm32-sdk")] {
132
133 #[wasm_bindgen]
134 impl TransactionOutpoint {
135 #[wasm_bindgen(constructor)]
136 pub fn ctor(transaction_id: TransactionId, index: u32) -> TransactionOutpoint {
137 Self { inner: Arc::new(TransactionOutpointInner { transaction_id, index }) }
138 }
139
140 #[wasm_bindgen(js_name = "getId")]
141 pub fn id_string(&self) -> String {
142 format!("{}-{}", self.get_transaction_id_as_string(), self.get_index())
143 }
144
145 #[wasm_bindgen(getter, js_name = transactionId)]
146 pub fn get_transaction_id_as_string(&self) -> String {
147 self.inner().transaction_id.to_string()
148 }
149
150 #[wasm_bindgen(getter, js_name = index)]
151 pub fn get_index(&self) -> TransactionIndexType {
152 self.inner().index
153 }
154 }
155 }
156}
157
158impl std::fmt::Display for TransactionOutpoint {
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 let inner = self.inner();
161 write!(f, "({}, {})", inner.transaction_id, inner.index)
162 }
163}
164
165impl TryFrom<&JsValue> for TransactionOutpoint {
166 type Error = Error;
167 fn try_from(js_value: &JsValue) -> Result<Self, Self::Error> {
168 let inner: TransactionOutpointInner = js_value.as_ref().try_into()?;
169 Ok(TransactionOutpoint { inner: Arc::new(inner) })
170 }
171}
172
173impl From<cctx::TransactionOutpoint> for TransactionOutpoint {
174 fn from(outpoint: cctx::TransactionOutpoint) -> Self {
175 let transaction_id = outpoint.transaction_id;
176 let index = outpoint.index;
177 TransactionOutpoint::new(transaction_id, index)
178 }
179}
180
181impl From<TransactionOutpoint> for cctx::TransactionOutpoint {
182 fn from(outpoint: TransactionOutpoint) -> Self {
183 let inner = outpoint.inner();
184 let transaction_id = inner.transaction_id;
185 let index = inner.index;
186 cctx::TransactionOutpoint::new(transaction_id, index)
187 }
188}
189
190impl From<&TransactionOutpoint> for cctx::TransactionOutpoint {
191 fn from(outpoint: &TransactionOutpoint) -> Self {
192 let inner = outpoint.inner();
193 let transaction_id = inner.transaction_id;
194 let index = inner.index;
195 cctx::TransactionOutpoint::new(transaction_id, index)
196 }
197}
198
199impl TransactionOutpoint {
200 pub fn simulated() -> Self {
201 Self::new(TransactionId::from_slice(&rand::random::<[u8; kaspa_hashes::HASH_SIZE]>()), 0)
202 }
203}