hyperfuel_client/
from_arrow.rs

1use polars_arrow::array::{BinaryArray, StaticArray, UInt64Array, UInt8Array, Utf8Array};
2
3use crate::{
4    // simple_types::{Block, Log, Trace, Transaction},
5    ArrowBatch,
6};
7
8use hyperfuel_format::{
9    BlockHeader, Input, InputType, Output, OutputType, Receipt, ReceiptType, Transaction,
10    TransactionStatus, TransactionType,
11};
12
13/// Used to do ArrowBatch-Native Rust type conversions while consuming the input value.
14pub trait FromArrow: Sized {
15    /// Converts to the Vector type from the ArrowBatch type.
16    fn from_arrow(batch: &ArrowBatch) -> Vec<Self>;
17}
18
19fn map_binary<'a, T>(i: usize, arr: Option<&'a BinaryArray<i32>>) -> Option<T>
20where
21    T: TryFrom<&'a [u8]>,
22    <T as TryFrom<&'a [u8]>>::Error: std::fmt::Debug,
23{
24    arr.and_then(|arr| arr.get(i).map(|v| v.try_into().unwrap()))
25}
26
27// Some unwraps etc that should be improved
28
29impl FromArrow for BlockHeader {
30    fn from_arrow(batch: &ArrowBatch) -> Vec<Self> {
31        let id = batch.column::<BinaryArray<i32>>("id").ok();
32        let da_height = batch.column::<UInt64Array>("da_height").ok();
33        let transactions_count = batch.column::<UInt64Array>("transactions_count").ok();
34        let consensus_parameters_version = batch
35            .column::<UInt64Array>("consensus_parameters_version")
36            .ok();
37        let state_transition_bytecode_version = batch
38            .column::<UInt64Array>("state_transition_bytecode_version")
39            .ok();
40        let message_receipt_count = batch.column::<UInt64Array>("message_receipt_count").ok();
41        let transactions_root = batch.column::<BinaryArray<i32>>("transactions_root").ok();
42        let message_outbox_root = batch.column::<BinaryArray<i32>>("message_outbox_root").ok();
43        let event_inbox_root = batch.column::<BinaryArray<i32>>("event_inbox_root").ok();
44        let height = batch.column::<UInt64Array>("height").ok();
45        let prev_root = batch.column::<BinaryArray<i32>>("prev_root").ok();
46        let time = batch.column::<UInt64Array>("time").ok();
47        let application_hash = batch.column::<BinaryArray<i32>>("application_hash").ok();
48
49        (0..batch.chunk.len())
50            .map(|idx| Self {
51                id: map_binary(idx, id).unwrap(),
52                da_height: da_height
53                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
54                    .expect("Construct from_arrow da_height"),
55                transactions_count: transactions_count
56                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
57                    .expect("Construct from_arrow transactions_count"),
58                consensus_parameters_version: consensus_parameters_version
59                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
60                    .expect("Construct from_arrow da_height"),
61                state_transition_bytecode_version: state_transition_bytecode_version
62                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
63                    .expect("Construct from_arrow state_transition_bytecode_version"),
64                message_receipt_count: message_receipt_count
65                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
66                    .expect("Construct from_arrow message_receipt_count"),
67                transactions_root: map_binary(idx, transactions_root)
68                    .expect("Construct from_arrow transactions_root"),
69                message_outbox_root: map_binary(idx, message_outbox_root)
70                    .expect("Construct from_arrow message_outbox_root"),
71                event_inbox_root: map_binary(idx, event_inbox_root)
72                    .expect("Construct from_arrow event_inbox_root"),
73                height: height
74                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
75                    .expect("Construct from_arrow height"),
76                prev_root: map_binary(idx, prev_root).expect("Construct from_arrow prev_root"),
77                time: time
78                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
79                    .expect("Construct from_arrow time"),
80                application_hash: map_binary(idx, application_hash)
81                    .expect("Construct from_arrow application_hash"),
82            })
83            .collect()
84    }
85}
86
87impl FromArrow for Transaction {
88    fn from_arrow(batch: &ArrowBatch) -> Vec<Self> {
89        let block_height = batch.column::<UInt64Array>("block_height").ok();
90        let id = batch.column::<BinaryArray<i32>>("id").ok();
91        let input_asset_ids = batch.column::<BinaryArray<i32>>("input_asset_ids").ok();
92        let input_contracts = batch.column::<BinaryArray<i32>>("input_contracts").ok();
93        let input_contract_utxo_id = batch
94            .column::<BinaryArray<i32>>("input_contract_utxo_id")
95            .ok();
96        let input_contract_balance_root = batch
97            .column::<BinaryArray<i32>>("input_contract_balance_root")
98            .ok();
99        let input_contract_state_root = batch
100            .column::<BinaryArray<i32>>("input_contract_state_root")
101            .ok();
102        let input_contract_tx_pointer_block_height = batch
103            .column::<UInt64Array>("input_contract_tx_pointer_block_height")
104            .ok();
105        let input_contract_tx_pointer_tx_index = batch
106            .column::<UInt64Array>("input_contract_tx_pointer_tx_index")
107            .ok();
108        let input_contract = batch.column::<BinaryArray<i32>>("input_contract").ok();
109        let policies_tip = batch.column::<UInt64Array>("policies_tip").ok();
110        let policies_witness_limit = batch.column::<UInt64Array>("policies_witness_limit").ok();
111        let policies_maturity = batch.column::<UInt64Array>("policies_maturity").ok();
112        let policies_max_fee = batch.column::<UInt64Array>("policies_max_fee").ok();
113        let script_gas_limit = batch.column::<UInt64Array>("script_gas_limit").ok();
114        let maturity = batch.column::<UInt64Array>("maturity").ok();
115        let mint_amount = batch.column::<UInt64Array>("mint_amount").ok();
116        let mint_asset_id = batch.column::<BinaryArray<i32>>("mint_asset_id").ok();
117        let mint_gas_price = batch.column::<UInt64Array>("mint_gas_price").ok();
118        let tx_pointer_block_height = batch.column::<UInt64Array>("tx_pointer_block_height").ok();
119        let tx_pointer_tx_index = batch.column::<UInt64Array>("tx_pointer_tx_index").ok();
120        let tx_type = batch.column::<UInt8Array>("tx_type").ok();
121        let output_contract_input_index = batch
122            .column::<UInt64Array>("output_contract_input_index")
123            .ok();
124        let output_contract_balance_root = batch
125            .column::<BinaryArray<i32>>("output_contract_balance_root")
126            .ok();
127        let output_contract_state_root = batch
128            .column::<BinaryArray<i32>>("output_contract_state_root")
129            .ok();
130        let witnesses = batch.column::<BinaryArray<i32>>("witnesses").ok();
131        let receipts_root = batch.column::<BinaryArray<i32>>("receipts_root").ok();
132        let status = batch.column::<UInt8Array>("status").ok();
133        let time = batch.column::<UInt64Array>("time").ok();
134        let reason = batch.column::<Utf8Array<i32>>("reason").ok();
135        let script = batch.column::<BinaryArray<i32>>("script").ok();
136        let script_data = batch.column::<BinaryArray<i32>>("script_data").ok();
137        let bytecode_witness_index = batch.column::<UInt64Array>("bytecode_witness_index").ok();
138        let bytecode_root = batch.column::<BinaryArray<i32>>("bytecode_root").ok();
139        let subsection_index = batch.column::<UInt64Array>("subsection_index").ok();
140        let subsections_number = batch.column::<UInt64Array>("subsections_number").ok();
141        let proof_set = batch.column::<BinaryArray<i32>>("proof_set").ok();
142        let consensus_parameters_upgrade_purpose_witness_index = batch
143            .column::<UInt64Array>("consensus_parameters_upgrade_purpose_witness_index")
144            .ok();
145        let consensus_parameters_upgrade_purpose_checksum = batch
146            .column::<BinaryArray<i32>>("consensus_parameters_upgrade_purpose_checksum")
147            .ok();
148        let state_transition_upgrade_purpose_root = batch
149            .column::<BinaryArray<i32>>("state_transition_upgrade_purpose_root")
150            .ok();
151        let salt = batch.column::<BinaryArray<i32>>("salt").ok();
152
153        (0..batch.chunk.len())
154            .map(|idx| Self {
155                block_height: block_height
156                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
157                    .expect("Construct from_arrow block_height"),
158                id: map_binary(idx, id).unwrap(),
159                input_asset_ids: input_asset_ids
160                    .and_then(|arr| arr.get(idx).map(|v| bincode::deserialize(v).unwrap())),
161                input_contracts: input_contracts
162                    .and_then(|arr| arr.get(idx).map(|v| bincode::deserialize(v).unwrap())),
163                input_contract_utxo_id: map_binary(idx, input_contract_utxo_id),
164                input_contract_balance_root: map_binary(idx, input_contract_balance_root),
165                input_contract_state_root: map_binary(idx, input_contract_state_root),
166                input_contract_tx_pointer_block_height: input_contract_tx_pointer_block_height
167                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
168                input_contract_tx_pointer_tx_index: input_contract_tx_pointer_tx_index
169                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
170                input_contract: map_binary(idx, input_contract),
171                policies_tip: policies_tip.and_then(|arr| arr.get(idx).map(|v| v.into())),
172                policies_witness_limit: policies_witness_limit
173                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
174                policies_maturity: policies_maturity.and_then(|arr| arr.get(idx).map(|v| v.into())),
175                policies_max_fee: policies_max_fee.and_then(|arr| arr.get(idx).map(|v| v.into())),
176                script_gas_limit: script_gas_limit.and_then(|arr| arr.get(idx).map(|v| v.into())),
177                maturity: maturity.and_then(|arr| arr.get(idx).map(|v| v.into())),
178                mint_amount: mint_amount.and_then(|arr| arr.get(idx).map(|v| v.into())),
179                mint_asset_id: map_binary(idx, mint_asset_id),
180                mint_gas_price: mint_gas_price.and_then(|arr| arr.get(idx).map(|v| v.into())),
181                tx_pointer_block_height: tx_pointer_block_height
182                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
183                tx_pointer_tx_index: tx_pointer_tx_index
184                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
185                tx_type: tx_type
186                    .and_then(|arr| arr.get(idx).map(TransactionType::from))
187                    .expect("Construct from_arrow tx_type"),
188                output_contract_input_index: output_contract_input_index
189                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
190                output_contract_balance_root: map_binary(idx, output_contract_balance_root),
191                output_contract_state_root: map_binary(idx, output_contract_state_root),
192                witnesses: map_binary(idx, witnesses),
193                receipts_root: map_binary(idx, receipts_root),
194                status: status
195                    .and_then(|arr| arr.get(idx).map(|v| TransactionStatus::from_u8(v).unwrap()))
196                    .expect("Construct from_arrow status"),
197                time: time
198                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
199                    .expect("Construct from_arrow time"),
200                reason: reason.and_then(|arr| arr.get(idx).map(|v| v.to_owned())),
201                script: map_binary(idx, script),
202                script_data: map_binary(idx, script_data),
203                bytecode_witness_index: bytecode_witness_index
204                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
205                bytecode_root: map_binary(idx, bytecode_root),
206                subsection_index: subsection_index.and_then(|arr| arr.get(idx).map(|v| v.into())),
207                subsections_number: subsections_number
208                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
209                proof_set: map_binary(idx, proof_set),
210                consensus_parameters_upgrade_purpose_witness_index:
211                    consensus_parameters_upgrade_purpose_witness_index
212                        .and_then(|arr| arr.get(idx).map(|v| v.into())),
213                consensus_parameters_upgrade_purpose_checksum: map_binary(
214                    idx,
215                    consensus_parameters_upgrade_purpose_checksum,
216                ),
217                state_transition_upgrade_purpose_root: map_binary(
218                    idx,
219                    state_transition_upgrade_purpose_root,
220                ),
221                salt: map_binary(idx, salt),
222            })
223            .collect()
224    }
225}
226
227impl FromArrow for Receipt {
228    fn from_arrow(batch: &ArrowBatch) -> Vec<Self> {
229        let receipt_index = batch.column::<UInt64Array>("receipt_index").ok();
230        let root_contract_id = batch.column::<BinaryArray<i32>>("root_contract_id").ok();
231        let tx_id = batch.column::<BinaryArray<i32>>("tx_id").ok();
232        let tx_status = batch.column::<UInt8Array>("tx_status").ok();
233        let tx_type = batch.column::<UInt8Array>("tx_type").ok();
234        let block_height = batch.column::<UInt64Array>("block_height").ok();
235        let pc = batch.column::<UInt64Array>("pc").ok();
236        let is = batch.column::<UInt64Array>("is").ok();
237        let to = batch.column::<BinaryArray<i32>>("to").ok();
238        let to_address = batch.column::<BinaryArray<i32>>("to_address").ok();
239        let amount = batch.column::<UInt64Array>("amount").ok();
240        let asset_id = batch.column::<BinaryArray<i32>>("asset_id").ok();
241        let gas = batch.column::<UInt64Array>("gas").ok();
242        let param1 = batch.column::<UInt64Array>("param1").ok();
243        let param2 = batch.column::<UInt64Array>("param2").ok();
244        let val = batch.column::<UInt64Array>("val").ok();
245        let ptr = batch.column::<UInt64Array>("ptr").ok();
246        let digest = batch.column::<BinaryArray<i32>>("digest").ok();
247        let reason = batch.column::<UInt64Array>("reason").ok();
248        let ra = batch.column::<UInt64Array>("ra").ok();
249        let rb = batch.column::<UInt64Array>("rb").ok();
250        let rc = batch.column::<UInt64Array>("rc").ok();
251        let rd = batch.column::<UInt64Array>("rd").ok();
252        let len = batch.column::<UInt64Array>("len").ok();
253        let receipt_type = batch.column::<UInt8Array>("receipt_type").ok();
254        let result = batch.column::<UInt64Array>("result").ok();
255        let gas_used = batch.column::<UInt64Array>("gas_used").ok();
256        let data = batch.column::<BinaryArray<i32>>("data").ok();
257        let sender = batch.column::<BinaryArray<i32>>("sender").ok();
258        let recipient = batch.column::<BinaryArray<i32>>("recipient").ok();
259        let nonce = batch.column::<UInt64Array>("nonce").ok();
260        let contract_id = batch.column::<BinaryArray<i32>>("contract_id").ok();
261        let sub_id = batch.column::<BinaryArray<i32>>("sub_id").ok();
262
263        (0..batch.chunk.len())
264            .map(|idx| Self {
265                receipt_index: receipt_index
266                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
267                    .expect("Construct from_arrow receipt_index"),
268                root_contract_id: map_binary(idx, root_contract_id),
269                tx_id: map_binary(idx, tx_id).expect("Construct from_arrow tx_id"),
270                tx_status: tx_status
271                    .and_then(|arr| arr.get(idx).map(|v| TransactionStatus::from_u8(v).unwrap()))
272                    .expect("Construct from_arrow tx_status"),
273                tx_type: tx_type
274                    .and_then(|arr| arr.get(idx).map(TransactionType))
275                    .expect("Construct from_arrow tx_type"),
276                block_height: block_height
277                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
278                    .expect("Construct from_arrow block_height"),
279                pc: pc.and_then(|arr| arr.get(idx).map(|v| v.into())),
280                is: is.and_then(|arr| arr.get(idx).map(|v| v.into())),
281                to: map_binary(idx, to),
282                to_address: map_binary(idx, to_address),
283                amount: amount.and_then(|arr| arr.get(idx).map(|v| v.into())),
284                asset_id: map_binary(idx, asset_id),
285                gas: gas.and_then(|arr| arr.get(idx).map(|v| v.into())),
286                param1: param1.and_then(|arr| arr.get(idx).map(|v| v.into())),
287                param2: param2.and_then(|arr| arr.get(idx).map(|v| v.into())),
288                val: val.and_then(|arr| arr.get(idx).map(|v| v.into())),
289                ptr: ptr.and_then(|arr| arr.get(idx).map(|v| v.into())),
290                digest: map_binary(idx, digest),
291                reason: reason.and_then(|arr| arr.get(idx).map(|v| v.into())),
292                ra: ra.and_then(|arr| arr.get(idx).map(|v| v.into())),
293                rb: rb.and_then(|arr| arr.get(idx).map(|v| v.into())),
294                rc: rc.and_then(|arr| arr.get(idx).map(|v| v.into())),
295                rd: rd.and_then(|arr| arr.get(idx).map(|v| v.into())),
296                len: len.and_then(|arr| arr.get(idx).map(|v| v.into())),
297                receipt_type: receipt_type
298                    .and_then(|arr| arr.get(idx).map(|v| ReceiptType::from_u8(v).unwrap()))
299                    .expect("Construct from_arrow receipt_type"),
300                result: result.and_then(|arr| arr.get(idx).map(|v| v.into())),
301                gas_used: gas_used.and_then(|arr| arr.get(idx).map(|v| v.into())),
302                data: map_binary(idx, data),
303                sender: map_binary(idx, sender),
304                recipient: map_binary(idx, recipient),
305                nonce: nonce.and_then(|arr| arr.get(idx).map(|v| v.into())),
306                contract_id: map_binary(idx, contract_id),
307                sub_id: map_binary(idx, sub_id),
308            })
309            .collect()
310    }
311}
312
313impl FromArrow for Input {
314    fn from_arrow(batch: &ArrowBatch) -> Vec<Self> {
315        let tx_id = batch.column::<BinaryArray<i32>>("tx_id").ok();
316        let tx_status = batch.column::<UInt8Array>("tx_status").ok();
317        let tx_type = batch.column::<UInt8Array>("tx_type").ok();
318        let block_height = batch.column::<UInt64Array>("block_height").ok();
319        let input_type = batch.column::<UInt8Array>("input_type").ok();
320        let utxo_id = batch.column::<BinaryArray<i32>>("utxo_id").ok();
321        let owner = batch.column::<BinaryArray<i32>>("owner").ok();
322        let amount = batch.column::<UInt64Array>("amount").ok();
323        let asset_id = batch.column::<BinaryArray<i32>>("asset_id").ok();
324        let tx_pointer_block_height = batch.column::<UInt64Array>("tx_pointer_block_height").ok();
325        let tx_pointer_tx_index = batch.column::<UInt64Array>("tx_pointer_tx_index").ok();
326        let witness_index = batch.column::<UInt64Array>("witness_index").ok();
327        let predicate_gas_used = batch.column::<UInt64Array>("predicate_gas_used").ok();
328        let predicate = batch.column::<BinaryArray<i32>>("predicate").ok();
329        let predicate_data = batch.column::<BinaryArray<i32>>("predicate_data").ok();
330        let balance_root = batch.column::<BinaryArray<i32>>("balance_root").ok();
331        let state_root = batch.column::<BinaryArray<i32>>("state_root").ok();
332        let contract = batch.column::<BinaryArray<i32>>("contract").ok();
333        let sender = batch.column::<BinaryArray<i32>>("sender").ok();
334        let recipient = batch.column::<BinaryArray<i32>>("recipient").ok();
335        let nonce = batch.column::<BinaryArray<i32>>("nonce").ok();
336        let data = batch.column::<BinaryArray<i32>>("data").ok();
337
338        (0..batch.chunk.len())
339            .map(|idx| Self {
340                tx_id: map_binary(idx, tx_id).unwrap(),
341                tx_status: tx_status
342                    .and_then(|arr| arr.get(idx).map(|v| TransactionStatus::from_u8(v).unwrap()))
343                    .expect("Construct from_arrow tx_status"),
344                tx_type: tx_type
345                    .and_then(|arr| arr.get(idx).map(TransactionType))
346                    .expect("Construct from_arrow tx_type"),
347                block_height: block_height
348                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
349                    .expect("Construct from_arrow block_height"),
350                input_type: input_type
351                    .and_then(|arr| arr.get(idx).map(|v| InputType::from_u8(v).unwrap()))
352                    .expect("Construct from_arrow input_type"),
353                utxo_id: map_binary(idx, utxo_id),
354                owner: map_binary(idx, owner),
355                amount: amount.and_then(|arr| arr.get(idx).map(|v| v.into())),
356                asset_id: map_binary(idx, asset_id),
357                tx_pointer_block_height: tx_pointer_block_height
358                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
359                tx_pointer_tx_index: tx_pointer_tx_index
360                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
361                witness_index: witness_index.and_then(|arr| arr.get(idx).map(|v| v.into())),
362                predicate_gas_used: predicate_gas_used
363                    .and_then(|arr| arr.get(idx).map(|v| v.into())),
364                predicate: map_binary(idx, predicate),
365                predicate_data: map_binary(idx, predicate_data),
366                balance_root: map_binary(idx, balance_root),
367                state_root: map_binary(idx, state_root),
368                contract: map_binary(idx, contract),
369                sender: map_binary(idx, sender),
370                recipient: map_binary(idx, recipient),
371                nonce: map_binary(idx, nonce),
372                data: map_binary(idx, data),
373            })
374            .collect()
375    }
376}
377
378impl FromArrow for Output {
379    fn from_arrow(batch: &ArrowBatch) -> Vec<Self> {
380        let tx_id = batch.column::<BinaryArray<i32>>("tx_id").ok();
381        let tx_status = batch.column::<UInt8Array>("tx_status").ok();
382        let tx_type = batch.column::<UInt8Array>("tx_type").ok();
383        let block_height = batch.column::<UInt64Array>("block_height").ok();
384        let output_type = batch.column::<UInt8Array>("output_type").ok();
385        let to = batch.column::<BinaryArray<i32>>("to").ok();
386        let amount = batch.column::<UInt64Array>("amount").ok();
387        let asset_id = batch.column::<BinaryArray<i32>>("asset_id").ok();
388        let input_index = batch.column::<UInt64Array>("input_index").ok();
389        let balance_root = batch.column::<BinaryArray<i32>>("balance_root").ok();
390        let state_root = batch.column::<BinaryArray<i32>>("state_root").ok();
391        let contract = batch.column::<BinaryArray<i32>>("contract").ok();
392
393        (0..batch.chunk.len())
394            .map(|idx| Self {
395                tx_id: map_binary(idx, tx_id).unwrap(),
396                tx_status: tx_status
397                    .and_then(|arr| arr.get(idx).map(|v| TransactionStatus::from_u8(v).unwrap()))
398                    .expect("Construct from_arrow tx_status"),
399                tx_type: tx_type
400                    .and_then(|arr| arr.get(idx).map(TransactionType))
401                    .expect("Construct from_arrow tx_type"),
402                block_height: block_height
403                    .and_then(|arr| arr.get(idx).map(|v| v.into()))
404                    .expect("Construct from_arrow block_height"),
405                output_type: output_type
406                    .and_then(|arr| arr.get(idx).map(|v| OutputType::from_u8(v).unwrap()))
407                    .expect("Construct from_arrow output_type"),
408                to: map_binary(idx, to),
409                amount: amount.and_then(|arr| arr.get(idx).map(|v| v.into())),
410                asset_id: map_binary(idx, asset_id),
411                input_index: input_index.and_then(|arr| arr.get(idx).map(|v| v.into())),
412                balance_root: map_binary(idx, balance_root),
413                state_root: map_binary(idx, state_root),
414                contract: map_binary(idx, contract),
415            })
416            .collect()
417    }
418}