Skip to content

Commit 6516155

Browse files
author
Ludo Galabru
committed
feat: add support for bitcoin op DelegatedStacking
1 parent c6c1c0e commit 6516155

File tree

2 files changed

+129
-4
lines changed
  • components
    • chainhook-event-observer/src/indexer/stacks
    • chainhook-types-rs/src

2 files changed

+129
-4
lines changed

components/chainhook-event-observer/src/indexer/stacks/mod.rs

+104-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ mod blocks_pool;
22

33
pub use blocks_pool::StacksBlockPool;
44

5+
use crate::chainhooks::stacks::try_decode_clarity_value;
56
use crate::indexer::AssetClassCache;
67
use crate::indexer::{IndexerConfig, StacksChainContext};
78
use crate::utils::Context;
89
use chainhook_types::*;
910
use clarity_repl::clarity::codec::StacksMessageCodec;
1011
use clarity_repl::clarity::util::hash::hex_bytes;
11-
use clarity_repl::clarity::vm::types::Value as ClarityValue;
12+
use clarity_repl::clarity::vm::types::{SequenceData, Value as ClarityValue};
1213
use clarity_repl::codec::{StacksTransaction, TransactionAuth, TransactionPayload};
1314
use hiro_system_kit::slog;
1415
use rocket::serde::json::Value as JsonValue;
@@ -539,8 +540,108 @@ pub fn get_tx_description(
539540
"stacked: {} µSTX by {} through Bitcoin transaction",
540541
data.locked_amount, data.locked_address,
541542
);
542-
let tx_type = StacksTransactionKind::Other;
543+
let tx_type =
544+
StacksTransactionKind::BitcoinOp(BitcoinOpData::StackSTX(StackSTXData {
545+
locked_amount: data.locked_amount,
546+
unlock_height: data.unlock_height,
547+
stacking_address: data.locked_address.clone(),
548+
}));
543549
return Ok((description, tx_type, 0, 0, data.locked_address, None));
550+
} else if let Some(ref event_data) = event.contract_event {
551+
let data: SmartContractEventData = serde_json::from_value(event_data.clone())
552+
.map_err(|e| format!("unable to decode event_data {}", e.to_string()))?;
553+
if let Some(ClarityValue::Response(data)) =
554+
try_decode_clarity_value(&data.hex_value)
555+
{
556+
if data.committed {
557+
if let ClarityValue::Tuple(outter) = *data.data {
558+
if let Some(ClarityValue::Tuple(inner)) = outter.data_map.get("data") {
559+
match (
560+
&outter.data_map.get("stacker"),
561+
&inner.data_map.get("amount-ustx"),
562+
&inner.data_map.get("delegate-to"),
563+
&inner.data_map.get("pox-addr"),
564+
&inner.data_map.get("unlock-burn-height"),
565+
) {
566+
(
567+
Some(ClarityValue::Principal(stacking_address)),
568+
Some(ClarityValue::UInt(amount_ustx)),
569+
Some(ClarityValue::Principal(delegate)),
570+
Some(ClarityValue::Optional(pox_addr)),
571+
Some(ClarityValue::Optional(unlock_burn_height)),
572+
) => {
573+
let description = format!(
574+
"stacked: {} µSTX delegated to {} through Bitcoin transaction",
575+
amount_ustx, delegate.to_string(),
576+
);
577+
let tx_type = StacksTransactionKind::BitcoinOp(
578+
BitcoinOpData::DelegateStackSTX(DelegateStackSTXData {
579+
stacking_address: stacking_address.to_string(),
580+
amount: amount_ustx.to_string(),
581+
delegate: delegate.to_string(),
582+
pox_address: match &pox_addr.data {
583+
Some(value) => match &**value {
584+
ClarityValue::Tuple(address_comps) => {
585+
match (
586+
&address_comps
587+
.data_map
588+
.get("version"),
589+
&address_comps
590+
.data_map
591+
.get("hashbytes"),
592+
) {
593+
(
594+
Some(ClarityValue::UInt(
595+
_version,
596+
)),
597+
Some(ClarityValue::Sequence(
598+
SequenceData::Buffer(
599+
_hashbytes,
600+
),
601+
)),
602+
) => None,
603+
_ => None,
604+
}
605+
}
606+
_ => None,
607+
},
608+
_ => None,
609+
},
610+
unlock_height: match &*(&unlock_burn_height.data) {
611+
Some(value) => match &**value {
612+
ClarityValue::UInt(value) => {
613+
Some(value.to_string())
614+
}
615+
_ => None,
616+
},
617+
_ => None,
618+
},
619+
}),
620+
);
621+
return Ok((
622+
description,
623+
tx_type,
624+
0,
625+
0,
626+
"".to_string(),
627+
None,
628+
));
629+
}
630+
_ => {}
631+
}
632+
}
633+
}
634+
}
635+
}
636+
} else {
637+
return Ok((
638+
"unsupported transaction".into(),
639+
StacksTransactionKind::Unsupported,
640+
0,
641+
0,
642+
"".to_string(),
643+
None,
644+
));
544645
}
545646
}
546647
return Err(format!(
@@ -627,7 +728,7 @@ pub fn get_tx_description(
627728
TransactionPayload::Coinbase(_, _) => {
628729
(format!("coinbase"), StacksTransactionKind::Coinbase)
629730
}
630-
_ => (format!("other"), StacksTransactionKind::Other),
731+
_ => (format!("other"), StacksTransactionKind::Unsupported),
631732
};
632733
Ok((description, tx_type, fee, nonce, sender, sponsor))
633734
}

components/chainhook-types-rs/src/rosetta.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,31 @@ pub enum StacksTransactionKind {
149149
ContractDeployment(StacksContractDeploymentData),
150150
NativeTokenTransfer,
151151
Coinbase,
152-
Other,
152+
BitcoinOp(BitcoinOpData),
153+
Unsupported,
154+
}
155+
156+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
157+
#[serde(tag = "type", content = "data")]
158+
pub enum BitcoinOpData {
159+
StackSTX(StackSTXData),
160+
DelegateStackSTX(DelegateStackSTXData),
161+
}
162+
163+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
164+
pub struct StackSTXData {
165+
pub locked_amount: String,
166+
pub unlock_height: String,
167+
pub stacking_address: String,
168+
}
169+
170+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
171+
pub struct DelegateStackSTXData {
172+
pub stacking_address: String,
173+
pub amount: String,
174+
pub delegate: String,
175+
pub pox_address: Option<String>,
176+
pub unlock_height: Option<String>,
153177
}
154178

155179
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]

0 commit comments

Comments
 (0)