Skip to content

Commit a37bb82

Browse files
committed
wip
1 parent 5beac89 commit a37bb82

File tree

1 file changed

+204
-6
lines changed

1 file changed

+204
-6
lines changed
Lines changed: 204 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1-
use crate::Result;
1+
use crate::{
2+
Result,
3+
client::{MiniBFClient, api::MiniBFApi, minibf::format_asset_id},
4+
};
5+
use blockfrost_openapi::models::{
6+
tx_content::TxContent, tx_content_output_amount_inner::TxContentOutputAmountInner,
7+
tx_content_utxo::TxContentUtxo,
8+
};
9+
use cardano_serialization_lib::PlutusData;
210
use sidechain_domain::*;
311
use sp_partner_chains_bridge::{
412
BridgeDataCheckpoint, BridgeTransferV1, MainChainScripts, TokenBridgeDataSource,
513
};
614
use std::marker::PhantomData;
715

816
pub struct TokenBridgeDataSourceImpl<RecipientAddress> {
17+
client: MiniBFClient,
918
_phantom: PhantomData<RecipientAddress>,
1019
}
1120

1221
impl<RecipientAddress> TokenBridgeDataSourceImpl<RecipientAddress> {
13-
pub fn new() -> Self {
14-
Self { _phantom: PhantomData::default() }
22+
pub fn new(client: MiniBFClient) -> Self {
23+
Self { client, _phantom: PhantomData::default() }
1524
}
1625
}
1726

@@ -22,10 +31,199 @@ impl<RecipientAddress: Send + Sync> TokenBridgeDataSource<RecipientAddress>
2231
async fn get_transfers(
2332
&self,
2433
_main_chain_scripts: MainChainScripts,
25-
_data_checkpoint: BridgeDataCheckpoint,
34+
data_checkpoint: BridgeDataCheckpoint,
2635
_max_transfers: u32,
27-
_current_mc_block: McBlockHash,
36+
current_mc_block_hash: McBlockHash,
2837
) -> Result<(Vec<BridgeTransferV1<RecipientAddress>>, BridgeDataCheckpoint)> {
29-
Err("not implemented".into())
38+
let current_mc_block = self.client.blocks_by_id(current_mc_block_hash).await?;
39+
40+
let data_checkpoint = match data_checkpoint {
41+
BridgeDataCheckpoint::Utxo(utxo) => {
42+
let TxBlockInfo { block_number, tx_ix } =
43+
get_block_info_for_utxo(&self.client, utxo.tx_hash.into()).await?.ok_or(
44+
format!(
45+
"Could not find block info for data checkpoint: {data_checkpoint:?}"
46+
),
47+
)?;
48+
ResolvedBridgeDataCheckpoint::Utxo {
49+
block_number,
50+
tx_ix,
51+
tx_out_ix: utxo.index.into(),
52+
}
53+
},
54+
BridgeDataCheckpoint::Block(number) => {
55+
ResolvedBridgeDataCheckpoint::Block { number: number.into() }
56+
},
57+
};
58+
59+
let asset = Asset {
60+
policy_id: main_chain_scripts.token_policy_id.into(),
61+
asset_name: main_chain_scripts.token_asset_name.into(),
62+
};
63+
let utxos = get_bridge_utxos_tx(
64+
&main_chain_scripts.illiquid_circulation_supply_validator_address.into(),
65+
asset,
66+
data_checkpoint,
67+
current_mc_block.block_no,
68+
Some(max_transfers),
69+
)
70+
.await?;
71+
72+
let new_checkpoint = match utxos.last() {
73+
None => BridgeDataCheckpoint::Block(current_mc_block.block_no.into()),
74+
Some(_) if (utxos.len() as u32) < max_transfers => {
75+
BridgeDataCheckpoint::Block(current_mc_block.block_no.into())
76+
},
77+
Some(utxo) => BridgeDataCheckpoint::Utxo(utxo.utxo_id()),
78+
};
79+
80+
let transfers = utxos.into_iter().flat_map(utxo_to_transfer).collect();
81+
82+
Ok((transfers, new_checkpoint))
83+
}
84+
}
85+
86+
pub(crate) struct BridgeUtxo {
87+
pub(crate) block_number: McBlockNumber,
88+
pub(crate) tx_ix: McTxIndexInBlock,
89+
pub(crate) tx_hash: McTxHash,
90+
pub(crate) utxo_ix: UtxoIndex,
91+
pub(crate) tokens_out: NativeTokenAmount,
92+
pub(crate) tokens_in: NativeTokenAmount,
93+
pub(crate) datum: Option<cardano_serialization_lib::PlutusData>,
94+
}
95+
96+
pub(crate) async fn get_block_info_for_utxo(
97+
client: &MiniBFClient,
98+
tx_hash: McTxHash,
99+
) -> Result<Option<TxBlockInfo>> {
100+
101+
// SELECT
102+
// block.block_no AS block_number,
103+
// tx.block_index AS tx_ix
104+
// FROM tx
105+
// JOIN block ON block.id = tx.block_id
106+
// WHERE tx.hash = $tx_hash
107+
}
108+
109+
pub(crate) enum ResolvedBridgeDataCheckpoint {
110+
Utxo { block_number: BlockNumber, tx_ix: TxIndexInBlock, tx_out_ix: TxIndex },
111+
Block { number: BlockNumber },
112+
}
113+
114+
pub(crate) async fn get_bridge_utxos_tx(
115+
client: &MiniBFClient,
116+
icp_address: &MainchainAddress,
117+
native_token: AssetId,
118+
checkpoint: ResolvedBridgeDataCheckpoint,
119+
to_block: McBlockNumber,
120+
max_utxos: Option<u32>,
121+
) -> Result<Vec<BridgeUtxo>> {
122+
let x = client.assets_transactions(native_token.clone()).await?;
123+
let y = x.into_iter().map(|a| async move {
124+
if a.block_height as u32 >= to_block.0 {
125+
let tx_hash = McTxHash::from_hex_unsafe(&a.tx_hash);
126+
let x = client.transactions_utxos(tx_hash).await?;
127+
let y = client.transaction_by_hash(tx_hash).await?;
128+
Result::Ok(Some((x, y)))
129+
} else {
130+
Result::Ok(None)
131+
}
132+
});
133+
let mut z = futures::future::try_join_all(y)
134+
.await?
135+
.iter()
136+
.flatten()
137+
.flat_map(|(x, y): &(TxContentUtxo, TxContent)| {
138+
let inputs = x.inputs.iter().filter(|i| i.address == icp_address.to_string());
139+
let outputs = x.outputs.iter().filter(|o| o.address == icp_address.to_string());
140+
let native_token = native_token.clone();
141+
outputs.map(move |output| {
142+
let native_token = native_token.clone();
143+
let output_tokens = get_all_tokens(&output.amount, &native_token.clone());
144+
let input_tokens = inputs
145+
.clone()
146+
.map(move |input| get_all_tokens(&input.amount, &native_token.clone()))
147+
.sum();
148+
149+
BridgeUtxo {
150+
block_number: McBlockNumber(y.block_height as u32),
151+
tokens_out: NativeTokenAmount(output_tokens),
152+
tokens_in: NativeTokenAmount(input_tokens),
153+
datum: output
154+
.inline_datum
155+
.clone()
156+
.map(|d| PlutusData::from_hex(&d).expect("valid datum")),
157+
tx_ix: todo!(),
158+
tx_hash: todo!(),
159+
utxo_ix: todo!(),
160+
}
161+
})
162+
})
163+
.collect::<Vec<_>>();
164+
165+
match checkpoint {
166+
ResolvedBridgeDataCheckpoint::Block { number } => {
167+
query_builder.push(&format!("AND block_no > {} ", number.0));
168+
},
169+
ResolvedBridgeDataCheckpoint::Utxo { block_number, tx_ix, tx_out_ix } => {
170+
query_builder.push(&format!(
171+
"AND (block_no, tx.block_index, outputs.index) > ({}, {}, {}) ",
172+
block_number.0, tx_ix.0, tx_out_ix.0
173+
));
174+
},
30175
}
176+
177+
query_builder.push("ORDER BY block.block_no, tx.block_index, outputs.index ");
178+
179+
if let Some(max_utxos) = max_utxos {
180+
query_builder.push(&format!("LIMIT {max_utxos}"));
181+
}
182+
183+
Err("not implemented".into())
31184
}
185+
186+
fn get_all_tokens(amount: &Vec<TxContentOutputAmountInner>, asset_id: &AssetId) -> u128 {
187+
amount
188+
.iter()
189+
.map(|v| {
190+
if v.unit == format_asset_id(asset_id) {
191+
v.quantity.parse::<u128>().expect("valid quantity is u128")
192+
} else {
193+
0u128
194+
}
195+
})
196+
.sum()
197+
}
198+
199+
// get_bridge_utxos_tx
200+
201+
/*
202+
* tx block no >= to_block
203+
* input : at icp address && token kind = assetid -> get SUM input token quantity
204+
* output: at icp address
205+
206+
SELECT
207+
block.block_no AS block_number
208+
, tx.block_index AS tx_ix
209+
, tx.hash AS tx_hash
210+
, outputs.index AS utxo_ix
211+
, output_tokens.quantity AS tokens_out
212+
, coalesce(sum(input_tokens.quantity), 0) AS tokens_in
213+
, datum.value AS datum
214+
FROM
215+
tx_out outputs
216+
JOIN tx ON outputs.tx_id = tx.id
217+
JOIN block ON tx.block_id = block.id
218+
JOIN ma_tx_out output_tokens ON output_tokens.tx_out_id = outputs.id
219+
JOIN multi_asset ON multi_asset.id = output_tokens.ident
220+
LEFT JOIN datum ON datum.hash = outputs.data_hash
221+
LEFT JOIN tx_out inputs ON inputs.consumed_by_tx_id = tx.id AND inputs.address = $icp_address
222+
LEFT JOIN ma_tx_out input_tokens ON input_tokens.tx_out_id = inputs.id AND input_tokens.ident = multi_asset.id
223+
224+
WHERE
225+
226+
multi_asset.policy = $native_token.policy_id AND multi_asset.name = $native_token.policy_name
227+
AND outputs.address = $icp_address
228+
AND block_no <= $to_block
229+
*/

0 commit comments

Comments
 (0)