Skip to main content

iota_analytics_indexer/handlers/
move_call_handler.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::sync::Arc;
6
7use anyhow::Result;
8use iota_data_ingestion_core::Worker;
9use iota_sdk_types::ObjectId;
10use iota_types::{full_checkpoint_content::CheckpointData, transaction::TransactionDataAPI};
11use tokio::sync::Mutex;
12
13use crate::{FileType, handlers::AnalyticsHandler, tables::MoveCallEntry};
14
15pub struct MoveCallHandler {
16    state: Mutex<State>,
17}
18
19struct State {
20    move_calls: Vec<MoveCallEntry>,
21}
22
23#[async_trait::async_trait]
24impl Worker for MoveCallHandler {
25    type Message = ();
26    type Error = anyhow::Error;
27
28    async fn process_checkpoint(
29        &self,
30        checkpoint_data: Arc<CheckpointData>,
31    ) -> Result<Self::Message, Self::Error> {
32        let CheckpointData {
33            checkpoint_summary,
34            transactions: checkpoint_transactions,
35            ..
36        } = checkpoint_data.as_ref();
37        let mut state = self.state.lock().await;
38        for checkpoint_transaction in checkpoint_transactions {
39            let move_calls = checkpoint_transaction
40                .transaction
41                .transaction_data()
42                .move_calls();
43            self.process_move_calls(
44                checkpoint_summary.epoch,
45                checkpoint_summary.sequence_number,
46                checkpoint_summary.timestamp_ms,
47                checkpoint_transaction.transaction.digest().to_base58(),
48                &move_calls,
49                &mut state,
50            );
51        }
52        Ok(())
53    }
54}
55
56#[async_trait::async_trait]
57impl AnalyticsHandler<MoveCallEntry> for MoveCallHandler {
58    async fn read(&self) -> Result<Vec<MoveCallEntry>> {
59        let mut state = self.state.lock().await;
60        let cloned = state.move_calls.clone();
61        state.move_calls.clear();
62        Ok(cloned)
63    }
64
65    fn file_type(&self) -> Result<FileType> {
66        Ok(FileType::MoveCall)
67    }
68
69    fn name(&self) -> &str {
70        "move_call"
71    }
72}
73
74impl MoveCallHandler {
75    pub fn new() -> Self {
76        let state = State { move_calls: vec![] };
77        Self {
78            state: Mutex::new(state),
79        }
80    }
81    fn process_move_calls(
82        &self,
83        epoch: u64,
84        checkpoint: u64,
85        timestamp_ms: u64,
86        transaction_digest: String,
87        move_calls: &[(&ObjectId, &str, &str)],
88        state: &mut State,
89    ) {
90        for (package, module, function) in move_calls.iter() {
91            let entry = MoveCallEntry {
92                transaction_digest: transaction_digest.clone(),
93                checkpoint,
94                epoch,
95                timestamp_ms,
96                package: package.to_string(),
97                module: module.to_string(),
98                function: function.to_string(),
99            };
100            state.move_calls.push(entry);
101        }
102    }
103}