Skip to content

Commit 36be496

Browse files
committed
Update dolos data source to use metadata
1 parent 22d7651 commit 36be496

File tree

4 files changed

+110
-70
lines changed

4 files changed

+110
-70
lines changed

toolkit/data-sources/dolos/src/bridge.rs

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
use crate::{
22
Result,
3-
client::{MiniBFClient, api::MiniBFApi, minibf::format_asset_id},
3+
client::{
4+
MiniBFClient, api::MiniBFApi, conversions::metadata_from_response, minibf::format_asset_id,
5+
},
46
};
57
use blockfrost_openapi::models::{
6-
tx_content::TxContent, tx_content_output_amount_inner::TxContentOutputAmountInner,
7-
tx_content_utxo::TxContentUtxo,
8+
tx_content::TxContent, tx_content_metadata_inner::TxContentMetadataInner,
9+
tx_content_output_amount_inner::TxContentOutputAmountInner, tx_content_utxo::TxContentUtxo,
10+
};
11+
use partner_chains_plutus_data::{
12+
VersionedMetadatum,
13+
bridge::{TokenTransferMetadatum, TokenTransferMetadatumV1},
814
};
9-
use cardano_serialization_lib::PlutusData;
10-
use partner_chains_plutus_data::bridge::{TokenTransferDatum, TokenTransferDatumV1};
1115
use sidechain_domain::*;
1216
use sp_partner_chains_bridge::{
1317
BridgeDataCheckpoint, BridgeTransferV1, MainChainScripts, TokenBridgeDataSource,
@@ -43,18 +47,12 @@ where
4347
let current_mc_block = self.client.blocks_by_id(current_mc_block_hash).await?;
4448

4549
let data_checkpoint = match data_checkpoint {
46-
BridgeDataCheckpoint::Utxo(utxo) => {
50+
BridgeDataCheckpoint::Tx(tx_hash) => {
4751
let TxBlockInfo { block_number, tx_ix } =
48-
get_block_info_for_utxo(&self.client, utxo.tx_hash.into()).await?.ok_or(
49-
format!(
50-
"Could not find block info for data checkpoint: {data_checkpoint:?}"
51-
),
52-
)?;
53-
ResolvedBridgeDataCheckpoint::Utxo {
54-
block_number,
55-
tx_ix,
56-
tx_out_ix: utxo.index.into(),
57-
}
52+
get_block_info_for_utxo(&self.client, tx_hash).await?.ok_or(format!(
53+
"Could not find block info for data checkpoint: {data_checkpoint:?}"
54+
))?;
55+
ResolvedBridgeDataCheckpoint::Tx { block_number, tx_ix }
5856
},
5957
BridgeDataCheckpoint::Block(number) => {
6058
ResolvedBridgeDataCheckpoint::Block { number: number.into() }
@@ -83,7 +81,7 @@ where
8381
Some(_) if (utxos.len() as u32) < max_transfers => {
8482
BridgeDataCheckpoint::Block(current_mc_block_height)
8583
},
86-
Some(utxo) => BridgeDataCheckpoint::Utxo(utxo.utxo_id()),
84+
Some(utxo) => BridgeDataCheckpoint::Tx(utxo.tx_hash),
8785
};
8886

8987
let transfers = utxos.into_iter().flat_map(utxo_to_transfer).collect();
@@ -107,22 +105,20 @@ where
107105
let token_amount = token_delta as u64;
108106

109107
let Some(datum) = utxo.datum.clone() else {
110-
return Some(BridgeTransferV1::InvalidTransfer { token_amount, utxo_id: utxo.utxo_id() });
108+
return Some(BridgeTransferV1::InvalidTransfer { token_amount, tx_hash: utxo.tx_hash });
111109
};
112110

113-
let transfer = match TokenTransferDatum::try_from(datum) {
114-
Ok(TokenTransferDatum::V1(TokenTransferDatumV1::UserTransfer { receiver })) => {
111+
let transfer = match TokenTransferMetadatum::decode(datum) {
112+
Ok(TokenTransferMetadatum::V1(TokenTransferMetadatumV1::UserTransfer { receiver })) => {
115113
match RecipientAddress::try_from(receiver.0.as_ref()) {
116114
Ok(recipient) => BridgeTransferV1::UserTransfer { token_amount, recipient },
117-
Err(_) => {
118-
BridgeTransferV1::InvalidTransfer { token_amount, utxo_id: utxo.utxo_id() }
119-
},
115+
Err(_) => BridgeTransferV1::InvalidTransfer { token_amount, tx_hash: utxo.tx_hash },
120116
}
121117
},
122-
Ok(TokenTransferDatum::V1(TokenTransferDatumV1::ReserveTransfer)) => {
118+
Ok(TokenTransferMetadatum::V1(TokenTransferMetadatumV1::ReserveTransfer)) => {
123119
BridgeTransferV1::ReserveTransfer { token_amount }
124120
},
125-
Err(_) => BridgeTransferV1::InvalidTransfer { token_amount, utxo_id: utxo.utxo_id() },
121+
Err(_) => BridgeTransferV1::InvalidTransfer { token_amount, tx_hash: utxo.tx_hash },
126122
};
127123

128124
Some(transfer)
@@ -132,23 +128,18 @@ pub(crate) struct BridgeUtxo {
132128
pub(crate) block_number: McBlockNumber,
133129
pub(crate) tx_ix: McTxIndexInBlock,
134130
pub(crate) tx_hash: McTxHash,
135-
pub(crate) utxo_ix: UtxoIndex,
136131
pub(crate) tokens_out: NativeTokenAmount,
137132
pub(crate) tokens_in: NativeTokenAmount,
138-
pub(crate) datum: Option<cardano_serialization_lib::PlutusData>,
133+
pub(crate) datum: Option<cardano_serialization_lib::TransactionMetadatum>,
139134
}
140135

141136
impl BridgeUtxo {
142-
pub(crate) fn utxo_id(&self) -> UtxoId {
143-
UtxoId { tx_hash: self.tx_hash.into(), index: self.utxo_ix.into() }
144-
}
145-
146137
pub(crate) fn ordering_key(&self) -> UtxoOrderingKey {
147-
(self.block_number, self.tx_ix, self.utxo_ix)
138+
(self.block_number, self.tx_ix)
148139
}
149140
}
150141

151-
pub(crate) type UtxoOrderingKey = (McBlockNumber, McTxIndexInBlock, UtxoIndex);
142+
pub(crate) type UtxoOrderingKey = (McBlockNumber, McTxIndexInBlock);
152143

153144
#[derive(Debug, Clone, PartialEq)]
154145
pub(crate) struct TxBlockInfo {
@@ -169,14 +160,14 @@ pub(crate) async fn get_block_info_for_utxo(
169160

170161
#[derive(Clone)]
171162
pub(crate) enum ResolvedBridgeDataCheckpoint {
172-
Utxo { block_number: McBlockNumber, tx_ix: McTxIndexInBlock, tx_out_ix: UtxoIndex },
163+
Tx { block_number: McBlockNumber, tx_ix: McTxIndexInBlock },
173164
Block { number: McBlockNumber },
174165
}
175166

176167
impl ResolvedBridgeDataCheckpoint {
177168
fn block_number(&self) -> McBlockNumber {
178169
match self {
179-
ResolvedBridgeDataCheckpoint::Utxo { block_number, .. } => *block_number,
170+
ResolvedBridgeDataCheckpoint::Tx { block_number, .. } => *block_number,
180171
ResolvedBridgeDataCheckpoint::Block { number } => *number,
181172
}
182173
}
@@ -198,48 +189,53 @@ pub(crate) async fn get_bridge_utxos_tx(
198189
let tx_hash = McTxHash::from_hex_unsafe(&a.tx_hash);
199190
let utxos = client.transactions_utxos(tx_hash).await?;
200191
let tx = client.transaction_by_hash(tx_hash).await?;
201-
Result::Ok(Some((utxos, tx)))
192+
let tx_metadata =
193+
client.transaction_metadata(&McTxHash::from_hex_unsafe(&tx.hash)).await?;
194+
Result::Ok(Some((utxos, tx_metadata, tx)))
202195
} else {
203196
Result::Ok(None)
204197
}
205198
});
206199
let mut bridge_utxos = futures::future::try_join_all(futures)
207200
.await?
208-
.iter()
201+
.into_iter()
209202
.flatten()
210-
.flat_map(|(utxos, tx): &(TxContentUtxo, TxContent)| {
211-
let inputs = utxos.inputs.iter().filter(|i| i.address == icp_address.to_string());
212-
let outputs = utxos.outputs.iter().filter(|o| o.address == icp_address.to_string());
203+
.filter(|(_, _, tx)| match checkpoint {
204+
ResolvedBridgeDataCheckpoint::Tx { block_number, tx_ix }
205+
if (tx.block_height, tx.index) <= (block_number.0 as i32, tx_ix.0 as i32) =>
206+
{
207+
false
208+
},
209+
ResolvedBridgeDataCheckpoint::Block { number }
210+
if tx.block_height <= number.0 as i32 =>
211+
{
212+
false
213+
},
214+
_ => true,
215+
})
216+
.flat_map(|(utxos, tx_metadata, tx): (TxContentUtxo, TxContentMetadataInner, TxContent)| {
213217
let native_token = native_token.clone();
214-
let checkpoint_clone = checkpoint.clone();
215-
outputs.filter_map(move |output| {
216-
let native_token = native_token.clone();
217-
let output_tokens = get_all_tokens(&output.amount, &native_token.clone());
218-
let input_tokens = inputs
219-
.clone()
220-
.map(move |input| get_all_tokens(&input.amount, &native_token.clone()))
221-
.sum();
218+
let input_tokens = utxos
219+
.inputs
220+
.iter()
221+
.filter(|i| i.address == icp_address.to_string())
222+
.map(|input| get_all_tokens(&input.amount, &native_token))
223+
.sum();
224+
225+
let output_tokens = utxos
226+
.outputs
227+
.iter()
228+
.filter(|o| o.address == icp_address.to_string())
229+
.map(|input| get_all_tokens(&input.amount, &native_token))
230+
.sum();
222231

223-
match checkpoint_clone {
224-
ResolvedBridgeDataCheckpoint::Utxo { tx_ix, tx_out_ix, .. }
225-
if tx.block_height <= tx_ix.0 as i32
226-
&& output.output_index <= tx_out_ix.0.into() =>
227-
{
228-
None
229-
},
230-
_ => Some(BridgeUtxo {
231-
block_number: McBlockNumber(tx.block_height as u32),
232-
tokens_out: NativeTokenAmount(output_tokens),
233-
tokens_in: NativeTokenAmount(input_tokens),
234-
datum: output
235-
.inline_datum
236-
.clone()
237-
.map(|d| PlutusData::from_hex(&d).expect("valid datum")),
238-
tx_ix: McTxIndexInBlock(tx.index as u32),
239-
tx_hash: McTxHash::from_hex_unsafe(&tx.hash),
240-
utxo_ix: UtxoIndex(output.output_index as u16),
241-
}),
242-
}
232+
Some(BridgeUtxo {
233+
block_number: McBlockNumber(tx.block_height as u32),
234+
tokens_out: NativeTokenAmount(output_tokens),
235+
tokens_in: NativeTokenAmount(input_tokens),
236+
datum: Some(metadata_from_response(tx_metadata).ok()?),
237+
tx_ix: McTxIndexInBlock(tx.index as u32),
238+
tx_hash: McTxHash::from_hex_unsafe(&tx.hash),
243239
})
244240
})
245241
.collect::<Vec<_>>();

toolkit/data-sources/dolos/src/client/api.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use blockfrost_openapi::models::{
66
block_content::BlockContent, epoch_param_content::EpochParamContent,
77
epoch_stake_pool_content_inner::EpochStakePoolContentInner, genesis_content::GenesisContent,
88
pool_history_inner::PoolHistoryInner, pool_list_extended_inner::PoolListExtendedInner,
9-
tx_content::TxContent, tx_content_utxo::TxContentUtxo,
9+
tx_content::TxContent, tx_content_metadata_inner::TxContentMetadataInner,
10+
tx_content_utxo::TxContentUtxo,
1011
};
1112
use sidechain_domain::*;
1213

@@ -148,4 +149,10 @@ pub trait MiniBFApi {
148149

149150
/// Return the information about blockchain genesis.
150151
async fn genesis(&self) -> Result<GenesisContent, DataSourceError>;
152+
153+
/// Returns metadata for a transaction
154+
async fn transaction_metadata(
155+
&self,
156+
tx_hash: &McTxHash,
157+
) -> Result<TxContentMetadataInner, DataSourceError>;
151158
}

toolkit/data-sources/dolos/src/client/conversions.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ use crate::{DataSourceError, Result};
22
use blockfrost_openapi::models::block_content::BlockContent;
33
use sidechain_domain::*;
44

5+
#[cfg(feature = "bridge")]
6+
use {
7+
blockfrost_openapi::models::{
8+
tx_content_metadata_inner::TxContentMetadataInner,
9+
tx_content_metadata_inner_json_metadata::TxContentMetadataInnerJsonMetadata,
10+
},
11+
cardano_serialization_lib::{MetadataMap, TransactionMetadatum},
12+
};
13+
514
pub fn from_block_content(value: BlockContent) -> Result<MainchainBlock> {
615
Ok(MainchainBlock {
716
number: value
@@ -20,3 +29,23 @@ pub fn from_block_content(value: BlockContent) -> Result<MainchainBlock> {
2029
timestamp: value.time as u64,
2130
})
2231
}
32+
33+
#[cfg(feature = "bridge")]
34+
pub(crate) fn metadata_from_response(
35+
value: TxContentMetadataInner,
36+
) -> Result<TransactionMetadatum> {
37+
let result = match *value.json_metadata.to_owned() {
38+
TxContentMetadataInnerJsonMetadata::String(s) => TransactionMetadatum::new_text(s)?,
39+
TxContentMetadataInnerJsonMetadata::Object(obj) => {
40+
let mut map = MetadataMap::new();
41+
for (key, value) in obj {
42+
let value = serde_json::from_value(value)?;
43+
map.insert_str(&key, &value)?;
44+
}
45+
46+
TransactionMetadatum::new_map(&map)
47+
},
48+
};
49+
50+
Ok(result)
51+
}

toolkit/data-sources/dolos/src/client/minibf.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use blockfrost_openapi::models::{
66
block_content::BlockContent, epoch_param_content::EpochParamContent,
77
epoch_stake_pool_content_inner::EpochStakePoolContentInner, genesis_content::GenesisContent,
88
pool_history_inner::PoolHistoryInner, pool_list_extended_inner::PoolListExtendedInner,
9-
tx_content::TxContent, tx_content_utxo::TxContentUtxo,
9+
tx_content::TxContent, tx_content_metadata_inner::TxContentMetadataInner,
10+
tx_content_utxo::TxContentUtxo,
1011
};
1112
use serde::de::DeserializeOwned;
1213
use sidechain_domain::*;
@@ -226,6 +227,13 @@ impl MiniBFApi for MiniBFClient {
226227
async fn genesis(&self) -> Result<GenesisContent, DataSourceError> {
227228
self.request("genesis").await
228229
}
230+
231+
async fn transaction_metadata(
232+
&self,
233+
tx_hash: &McTxHash,
234+
) -> Result<TxContentMetadataInner, DataSourceError> {
235+
self.request(&format!("txs/{tx_hash}/metadata")).await
236+
}
229237
}
230238

231239
pub fn format_asset_id(asset_id: &AssetId) -> String {

0 commit comments

Comments
 (0)