sui_graphql_rpc/types/
move_function.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use async_graphql::*;
5use sui_package_resolver::FunctionDef;
6
7use crate::error::Error;
8
9use super::{
10    move_module::MoveModule,
11    open_move_type::{abilities, MoveAbility, MoveVisibility, OpenMoveType},
12    sui_address::SuiAddress,
13};
14
15pub(crate) struct MoveFunction {
16    package: SuiAddress,
17    module: String,
18    name: String,
19    visibility: MoveVisibility,
20    is_entry: bool,
21    type_parameters: Vec<MoveFunctionTypeParameter>,
22    parameters: Vec<OpenMoveType>,
23    return_: Vec<OpenMoveType>,
24    checkpoint_viewed_at: u64,
25}
26
27#[derive(SimpleObject)]
28pub(crate) struct MoveFunctionTypeParameter {
29    constraints: Vec<MoveAbility>,
30}
31
32/// Signature of a function, defined in a Move module.
33#[Object]
34impl MoveFunction {
35    /// The module this function was defined in.
36    async fn module(&self, ctx: &Context<'_>) -> Result<MoveModule> {
37        let Some(module) =
38            MoveModule::query(ctx, self.package, &self.module, self.checkpoint_viewed_at)
39                .await
40                .extend()?
41        else {
42            return Err(Error::Internal(format!(
43                "Failed to load module for function: {}::{}::{}",
44                self.package, self.module, self.name,
45            )))
46            .extend();
47        };
48
49        Ok(module)
50    }
51
52    /// The function's (unqualified) name.
53    async fn name(&self) -> &str {
54        &self.name
55    }
56
57    /// The function's visibility: `public`, `public(friend)`, or `private`.
58    async fn visibility(&self) -> Option<&MoveVisibility> {
59        Some(&self.visibility)
60    }
61
62    /// Whether the function has the `entry` modifier or not.
63    async fn is_entry(&self) -> Option<bool> {
64        Some(self.is_entry)
65    }
66
67    /// Constraints on the function's formal type parameters.  Move bytecode does not name type
68    /// parameters, so when they are referenced (e.g. in parameter and return types) they are
69    /// identified by their index in this list.
70    async fn type_parameters(&self) -> Option<&Vec<MoveFunctionTypeParameter>> {
71        Some(&self.type_parameters)
72    }
73
74    /// The function's parameter types.  These types can reference type parameters introduce by this
75    /// function (see `typeParameters`).
76    async fn parameters(&self) -> Option<&Vec<OpenMoveType>> {
77        Some(&self.parameters)
78    }
79
80    /// The function's return types.  There can be multiple because functions in Move can return
81    /// multiple values.  These types can reference type parameters introduced by this function (see
82    /// `typeParameters`).
83    #[graphql(name = "return")]
84    async fn return_(&self) -> Option<&Vec<OpenMoveType>> {
85        Some(&self.return_)
86    }
87}
88
89impl MoveFunction {
90    pub(crate) fn new(
91        package: SuiAddress,
92        module: String,
93        name: String,
94        def: FunctionDef,
95        checkpoint_viewed_at: u64,
96    ) -> Self {
97        let type_parameters = def
98            .type_params
99            .into_iter()
100            .map(|constraints| MoveFunctionTypeParameter {
101                constraints: abilities(constraints),
102            })
103            .collect();
104
105        let parameters = def.parameters.into_iter().map(OpenMoveType::from).collect();
106        let return_ = def.return_.into_iter().map(OpenMoveType::from).collect();
107
108        MoveFunction {
109            package,
110            module,
111            name,
112            visibility: def.visibility.into(),
113            is_entry: def.is_entry,
114            type_parameters,
115            parameters,
116            return_,
117            checkpoint_viewed_at,
118        }
119    }
120
121    pub(crate) async fn query(
122        ctx: &Context<'_>,
123        address: SuiAddress,
124        module: &str,
125        function: &str,
126        checkpoint_viewed_at: u64,
127    ) -> Result<Option<Self>, Error> {
128        let Some(module) = MoveModule::query(ctx, address, module, checkpoint_viewed_at).await?
129        else {
130            return Ok(None);
131        };
132
133        module.function_impl(function.to_string())
134    }
135}