cherry_svm_schema/
lib.rs

1use std::sync::Arc;
2
3use arrow::array::builder;
4use arrow::datatypes::{DataType, Field, Fields, Schema};
5use arrow::record_batch::RecordBatch;
6
7pub fn blocks_schema() -> Schema {
8    Schema::new(vec![
9        Field::new("slot", DataType::UInt64, true),
10        Field::new("hash", DataType::Binary, true),
11        Field::new("parent_slot", DataType::UInt64, true),
12        Field::new("parent_hash", DataType::Binary, true),
13        Field::new("height", DataType::UInt64, true),
14        Field::new("timestamp", DataType::Int64, true),
15    ])
16}
17
18pub fn rewards_schema() -> Schema {
19    Schema::new(vec![
20        Field::new("block_slot", DataType::UInt64, true),
21        Field::new("block_hash", DataType::Binary, true),
22        Field::new("pubkey", DataType::Binary, true),
23        Field::new("lamports", DataType::Int64, true),
24        Field::new("post_balance", DataType::UInt64, true),
25        Field::new("reward_type", DataType::Utf8, true),
26        Field::new("commission", DataType::UInt8, true),
27    ])
28}
29
30pub fn token_balances_schema() -> Schema {
31    Schema::new(vec![
32        Field::new("block_slot", DataType::UInt64, true),
33        Field::new("block_hash", DataType::Binary, true),
34        Field::new("transaction_index", DataType::UInt32, true),
35        Field::new("account", DataType::Binary, true),
36        Field::new("pre_mint", DataType::Binary, true),
37        Field::new("post_mint", DataType::Binary, true),
38        Field::new("pre_decimals", DataType::UInt16, true),
39        Field::new("post_decimals", DataType::UInt16, true),
40        Field::new("pre_program_id", DataType::Binary, true),
41        Field::new("post_program_id", DataType::Binary, true),
42        Field::new("pre_owner", DataType::Binary, true),
43        Field::new("post_owner", DataType::Binary, true),
44        Field::new("pre_amount", DataType::UInt64, true),
45        Field::new("post_amount", DataType::UInt64, true),
46    ])
47}
48
49pub fn balances_schema() -> Schema {
50    Schema::new(vec![
51        Field::new("block_slot", DataType::UInt64, true),
52        Field::new("block_hash", DataType::Binary, true),
53        Field::new("transaction_index", DataType::UInt32, true),
54        Field::new("account", DataType::Binary, true),
55        Field::new("pre", DataType::UInt64, true),
56        Field::new("post", DataType::UInt64, true),
57    ])
58}
59
60pub fn logs_schema() -> Schema {
61    Schema::new(vec![
62        Field::new("block_slot", DataType::UInt64, true),
63        Field::new("block_hash", DataType::Binary, true),
64        Field::new("transaction_index", DataType::UInt32, true),
65        Field::new("log_index", DataType::UInt32, true),
66        Field::new(
67            "instruction_address",
68            DataType::List(Arc::new(Field::new("item", DataType::UInt32, true))),
69            true,
70        ),
71        Field::new("program_id", DataType::Binary, true),
72        Field::new("kind", DataType::Utf8, true),
73        Field::new("message", DataType::Utf8, true),
74    ])
75}
76
77pub fn transactions_schema() -> Schema {
78    Schema::new(vec![
79        Field::new("block_slot", DataType::UInt64, true),
80        Field::new("block_hash", DataType::Binary, true),
81        Field::new("transaction_index", DataType::UInt32, true),
82        Field::new("signature", DataType::Binary, true),
83        Field::new("version", DataType::Int8, true),
84        Field::new(
85            "account_keys",
86            DataType::List(Arc::new(Field::new("item", DataType::Binary, true))),
87            true,
88        ),
89        Field::new(
90            "address_table_lookups",
91            DataType::List(Arc::new(Field::new(
92                "item",
93                address_table_lookup_dt(),
94                true,
95            ))),
96            true,
97        ),
98        Field::new("num_readonly_signed_accounts", DataType::UInt32, true),
99        Field::new("num_readonly_unsigned_accounts", DataType::UInt32, true),
100        Field::new("num_required_signatures", DataType::UInt32, true),
101        Field::new("recent_blockhash", DataType::Binary, true),
102        Field::new(
103            "signatures",
104            DataType::List(Arc::new(Field::new("item", DataType::Binary, true))),
105            true,
106        ),
107        // encoded as json string
108        Field::new("err", DataType::Utf8, true),
109        Field::new("fee", DataType::UInt64, true),
110        Field::new("compute_units_consumed", DataType::UInt64, true),
111        Field::new(
112            "loaded_readonly_addresses",
113            DataType::List(Arc::new(Field::new("item", DataType::Binary, true))),
114            true,
115        ),
116        Field::new(
117            "loaded_writable_addresses",
118            DataType::List(Arc::new(Field::new("item", DataType::Binary, true))),
119            true,
120        ),
121        Field::new("fee_payer", DataType::Binary, true),
122        Field::new("has_dropped_log_messages", DataType::Boolean, true),
123    ])
124}
125
126fn address_table_lookup_dt() -> DataType {
127    DataType::Struct(Fields::from(vec![
128        Arc::new(Field::new("account_key", DataType::Binary, true)),
129        Arc::new(Field::new(
130            "writable_indexes",
131            DataType::List(Arc::new(Field::new("item", DataType::UInt64, true))),
132            true,
133        )),
134        Arc::new(Field::new(
135            "readonly_indexes",
136            DataType::List(Arc::new(Field::new("item", DataType::UInt64, true))),
137            true,
138        )),
139    ]))
140}
141
142pub fn instructions_schema() -> Schema {
143    Schema::new(vec![
144        Field::new("block_slot", DataType::UInt64, true),
145        Field::new("block_hash", DataType::Binary, true),
146        Field::new("transaction_index", DataType::UInt32, true),
147        Field::new(
148            "instruction_address",
149            DataType::List(Arc::new(Field::new("item", DataType::UInt32, true))),
150            true,
151        ),
152        Field::new("program_id", DataType::Binary, true),
153        Field::new("a0", DataType::Binary, true),
154        Field::new("a1", DataType::Binary, true),
155        Field::new("a2", DataType::Binary, true),
156        Field::new("a3", DataType::Binary, true),
157        Field::new("a4", DataType::Binary, true),
158        Field::new("a5", DataType::Binary, true),
159        Field::new("a6", DataType::Binary, true),
160        Field::new("a7", DataType::Binary, true),
161        Field::new("a8", DataType::Binary, true),
162        Field::new("a9", DataType::Binary, true),
163        // accounts starting from index 10
164        Field::new(
165            "rest_of_accounts",
166            DataType::List(Arc::new(Field::new("item", DataType::Binary, true))),
167            true,
168        ),
169        Field::new("data", DataType::Binary, true),
170        Field::new("d1", DataType::Binary, true),
171        Field::new("d2", DataType::Binary, true),
172        Field::new("d4", DataType::Binary, true),
173        Field::new("d8", DataType::Binary, true),
174        Field::new("error", DataType::Utf8, true),
175        Field::new("compute_units_consumed", DataType::UInt64, true),
176        Field::new("is_committed", DataType::Boolean, true),
177        Field::new("has_dropped_log_messages", DataType::Boolean, true),
178    ])
179}
180
181#[derive(Default)]
182pub struct BlocksBuilder {
183    pub slot: builder::UInt64Builder,
184    pub hash: builder::BinaryBuilder,
185    pub parent_slot: builder::UInt64Builder,
186    pub parent_hash: builder::BinaryBuilder,
187    pub height: builder::UInt64Builder,
188    pub timestamp: builder::Int64Builder,
189}
190
191impl BlocksBuilder {
192    pub fn finish(mut self) -> RecordBatch {
193        RecordBatch::try_new(
194            Arc::new(blocks_schema()),
195            vec![
196                Arc::new(self.slot.finish()),
197                Arc::new(self.hash.finish()),
198                Arc::new(self.parent_slot.finish()),
199                Arc::new(self.parent_hash.finish()),
200                Arc::new(self.height.finish()),
201                Arc::new(self.timestamp.finish()),
202            ],
203        )
204        .unwrap()
205    }
206}
207
208#[derive(Default)]
209pub struct RewardsBuilder {
210    pub block_slot: builder::UInt64Builder,
211    pub block_hash: builder::BinaryBuilder,
212    pub pubkey: builder::BinaryBuilder,
213    pub lamports: builder::Int64Builder,
214    pub post_balance: builder::UInt64Builder,
215    pub reward_type: builder::StringBuilder,
216    pub commission: builder::UInt8Builder,
217}
218
219impl RewardsBuilder {
220    pub fn finish(mut self) -> RecordBatch {
221        RecordBatch::try_new(
222            Arc::new(rewards_schema()),
223            vec![
224                Arc::new(self.block_slot.finish()),
225                Arc::new(self.block_hash.finish()),
226                Arc::new(self.pubkey.finish()),
227                Arc::new(self.lamports.finish()),
228                Arc::new(self.post_balance.finish()),
229                Arc::new(self.reward_type.finish()),
230                Arc::new(self.commission.finish()),
231            ],
232        )
233        .unwrap()
234    }
235}
236
237#[derive(Default)]
238pub struct TokenBalancesBuilder {
239    pub block_slot: builder::UInt64Builder,
240    pub block_hash: builder::BinaryBuilder,
241    pub transaction_index: builder::UInt32Builder,
242    pub account: builder::BinaryBuilder,
243    pub pre_mint: builder::BinaryBuilder,
244    pub post_mint: builder::BinaryBuilder,
245    pub pre_decimals: builder::UInt16Builder,
246    pub post_decimals: builder::UInt16Builder,
247    pub pre_program_id: builder::BinaryBuilder,
248    pub post_program_id: builder::BinaryBuilder,
249    pub pre_owner: builder::BinaryBuilder,
250    pub post_owner: builder::BinaryBuilder,
251    pub pre_amount: builder::UInt64Builder,
252    pub post_amount: builder::UInt64Builder,
253}
254
255impl TokenBalancesBuilder {
256    pub fn finish(mut self) -> RecordBatch {
257        RecordBatch::try_new(
258            Arc::new(token_balances_schema()),
259            vec![
260                Arc::new(self.block_slot.finish()),
261                Arc::new(self.block_hash.finish()),
262                Arc::new(self.transaction_index.finish()),
263                Arc::new(self.account.finish()),
264                Arc::new(self.pre_mint.finish()),
265                Arc::new(self.post_mint.finish()),
266                Arc::new(self.pre_decimals.finish()),
267                Arc::new(self.post_decimals.finish()),
268                Arc::new(self.pre_program_id.finish()),
269                Arc::new(self.post_program_id.finish()),
270                Arc::new(self.pre_owner.finish()),
271                Arc::new(self.post_owner.finish()),
272                Arc::new(self.pre_amount.finish()),
273                Arc::new(self.post_amount.finish()),
274            ],
275        )
276        .unwrap()
277    }
278}
279
280#[derive(Default)]
281pub struct BalancesBuilder {
282    pub block_slot: builder::UInt64Builder,
283    pub block_hash: builder::BinaryBuilder,
284    pub transaction_index: builder::UInt32Builder,
285    pub account: builder::BinaryBuilder,
286    pub pre: builder::UInt64Builder,
287    pub post: builder::UInt64Builder,
288}
289
290impl BalancesBuilder {
291    pub fn finish(mut self) -> RecordBatch {
292        RecordBatch::try_new(
293            Arc::new(balances_schema()),
294            vec![
295                Arc::new(self.block_slot.finish()),
296                Arc::new(self.block_hash.finish()),
297                Arc::new(self.transaction_index.finish()),
298                Arc::new(self.account.finish()),
299                Arc::new(self.pre.finish()),
300                Arc::new(self.post.finish()),
301            ],
302        )
303        .unwrap()
304    }
305}
306
307#[derive(Default)]
308pub struct LogsBuilder {
309    pub block_slot: builder::UInt64Builder,
310    pub block_hash: builder::BinaryBuilder,
311    pub transaction_index: builder::UInt32Builder,
312    pub log_index: builder::UInt32Builder,
313    pub instruction_address: builder::ListBuilder<builder::UInt32Builder>,
314    pub program_id: builder::BinaryBuilder,
315    pub kind: builder::StringBuilder,
316    pub message: builder::StringBuilder,
317}
318
319impl LogsBuilder {
320    pub fn finish(mut self) -> RecordBatch {
321        RecordBatch::try_new(
322            Arc::new(logs_schema()),
323            vec![
324                Arc::new(self.block_slot.finish()),
325                Arc::new(self.block_hash.finish()),
326                Arc::new(self.transaction_index.finish()),
327                Arc::new(self.log_index.finish()),
328                Arc::new(self.instruction_address.finish()),
329                Arc::new(self.program_id.finish()),
330                Arc::new(self.kind.finish()),
331                Arc::new(self.message.finish()),
332            ],
333        )
334        .unwrap()
335    }
336}
337
338#[derive(Default)]
339pub struct TransactionsBuilder {
340    pub block_slot: builder::UInt64Builder,
341    pub block_hash: builder::BinaryBuilder,
342    pub transaction_index: builder::UInt32Builder,
343    pub signature: builder::BinaryBuilder,
344    pub version: builder::Int8Builder,
345    pub account_keys: builder::ListBuilder<builder::BinaryBuilder>,
346    pub address_table_lookups: AddressTableLookupsBuilder,
347    pub num_readonly_signed_accounts: builder::UInt32Builder,
348    pub num_readonly_unsigned_accounts: builder::UInt32Builder,
349    pub num_required_signatures: builder::UInt32Builder,
350    pub recent_blockhash: builder::BinaryBuilder,
351    pub signatures: builder::ListBuilder<builder::BinaryBuilder>,
352    pub err: builder::StringBuilder,
353    pub fee: builder::UInt64Builder,
354    pub compute_units_consumed: builder::UInt64Builder,
355    pub loaded_readonly_addresses: builder::ListBuilder<builder::BinaryBuilder>,
356    pub loaded_writable_addresses: builder::ListBuilder<builder::BinaryBuilder>,
357    pub fee_payer: builder::BinaryBuilder,
358    pub has_dropped_log_messages: builder::BooleanBuilder,
359}
360
361pub struct AddressTableLookupsBuilder(pub builder::ListBuilder<builder::StructBuilder>);
362
363impl Default for AddressTableLookupsBuilder {
364    fn default() -> Self {
365        Self(builder::ListBuilder::new(builder::StructBuilder::new(
366            match address_table_lookup_dt() {
367                DataType::Struct(fields) => fields,
368                _ => unreachable!(),
369            },
370            vec![
371                Box::new(builder::BinaryBuilder::default()),
372                Box::new(builder::ListBuilder::new(builder::UInt64Builder::default())),
373                Box::new(builder::ListBuilder::new(builder::UInt64Builder::default())),
374            ],
375        )))
376    }
377}
378
379impl TransactionsBuilder {
380    pub fn finish(mut self) -> RecordBatch {
381        RecordBatch::try_new(
382            Arc::new(transactions_schema()),
383            vec![
384                Arc::new(self.block_slot.finish()),
385                Arc::new(self.block_hash.finish()),
386                Arc::new(self.transaction_index.finish()),
387                Arc::new(self.signature.finish()),
388                Arc::new(self.version.finish()),
389                Arc::new(self.account_keys.finish()),
390                Arc::new(self.address_table_lookups.0.finish()),
391                Arc::new(self.num_readonly_signed_accounts.finish()),
392                Arc::new(self.num_readonly_unsigned_accounts.finish()),
393                Arc::new(self.num_required_signatures.finish()),
394                Arc::new(self.recent_blockhash.finish()),
395                Arc::new(self.signatures.finish()),
396                Arc::new(self.err.finish()),
397                Arc::new(self.fee.finish()),
398                Arc::new(self.compute_units_consumed.finish()),
399                Arc::new(self.loaded_readonly_addresses.finish()),
400                Arc::new(self.loaded_writable_addresses.finish()),
401                Arc::new(self.fee_payer.finish()),
402                Arc::new(self.has_dropped_log_messages.finish()),
403            ],
404        )
405        .unwrap()
406    }
407}
408
409#[derive(Default)]
410pub struct InstructionsBuilder {
411    pub block_slot: builder::UInt64Builder,
412    pub block_hash: builder::BinaryBuilder,
413    pub transaction_index: builder::UInt32Builder,
414    pub instruction_address: builder::ListBuilder<builder::UInt32Builder>,
415    pub program_id: builder::BinaryBuilder,
416    pub a0: builder::BinaryBuilder,
417    pub a1: builder::BinaryBuilder,
418    pub a2: builder::BinaryBuilder,
419    pub a3: builder::BinaryBuilder,
420    pub a4: builder::BinaryBuilder,
421    pub a5: builder::BinaryBuilder,
422    pub a6: builder::BinaryBuilder,
423    pub a7: builder::BinaryBuilder,
424    pub a8: builder::BinaryBuilder,
425    pub a9: builder::BinaryBuilder,
426    pub rest_of_accounts: builder::ListBuilder<builder::BinaryBuilder>,
427    pub data: builder::BinaryBuilder,
428    pub d1: builder::BinaryBuilder,
429    pub d2: builder::BinaryBuilder,
430    pub d4: builder::BinaryBuilder,
431    pub d8: builder::BinaryBuilder,
432    pub error: builder::StringBuilder,
433    pub compute_units_consumed: builder::UInt64Builder,
434    pub is_committed: builder::BooleanBuilder,
435    pub has_dropped_log_messages: builder::BooleanBuilder,
436}
437
438impl InstructionsBuilder {
439    pub fn finish(mut self) -> RecordBatch {
440        RecordBatch::try_new(
441            Arc::new(instructions_schema()),
442            vec![
443                Arc::new(self.block_slot.finish()),
444                Arc::new(self.block_hash.finish()),
445                Arc::new(self.transaction_index.finish()),
446                Arc::new(self.instruction_address.finish()),
447                Arc::new(self.program_id.finish()),
448                Arc::new(self.a0.finish()),
449                Arc::new(self.a1.finish()),
450                Arc::new(self.a2.finish()),
451                Arc::new(self.a3.finish()),
452                Arc::new(self.a4.finish()),
453                Arc::new(self.a5.finish()),
454                Arc::new(self.a6.finish()),
455                Arc::new(self.a7.finish()),
456                Arc::new(self.a8.finish()),
457                Arc::new(self.a9.finish()),
458                Arc::new(self.rest_of_accounts.finish()),
459                Arc::new(self.data.finish()),
460                Arc::new(self.d1.finish()),
461                Arc::new(self.d2.finish()),
462                Arc::new(self.d4.finish()),
463                Arc::new(self.d8.finish()),
464                Arc::new(self.error.finish()),
465                Arc::new(self.compute_units_consumed.finish()),
466                Arc::new(self.is_committed.finish()),
467                Arc::new(self.has_dropped_log_messages.finish()),
468            ],
469        )
470        .unwrap()
471    }
472}
473
474#[cfg(test)]
475mod tests {
476    use super::*;
477
478    #[test]
479    fn smoke() {
480        BlocksBuilder::default().finish();
481        RewardsBuilder::default().finish();
482        TokenBalancesBuilder::default().finish();
483        BalancesBuilder::default().finish();
484        LogsBuilder::default().finish();
485        TransactionsBuilder::default().finish();
486        InstructionsBuilder::default().finish();
487    }
488}