sui_indexer_alt_jsonrpc/api/move_utils/
response.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use anyhow::anyhow;
5use move_binary_format::file_format::Ability;
6use move_binary_format::file_format::AbilitySet;
7use move_binary_format::file_format::Visibility;
8use sui_json_rpc_types::SuiMoveAbility;
9use sui_json_rpc_types::SuiMoveAbilitySet;
10use sui_json_rpc_types::SuiMoveNormalizedFunction;
11use sui_json_rpc_types::SuiMoveNormalizedType;
12use sui_json_rpc_types::SuiMoveVisibility;
13use sui_package_resolver::FunctionDef;
14use sui_package_resolver::OpenSignature;
15use sui_package_resolver::OpenSignatureBody;
16use sui_package_resolver::Reference;
17use sui_types::Identifier;
18use sui_types::base_types::ObjectID;
19
20use crate::api::move_utils::error::Error;
21use crate::context::Context;
22use crate::error::RpcError;
23use crate::error::invalid_params;
24
25/// Load information about a function, and convert it into a JSON-RPC response.
26pub(super) async fn function(
27    ctx: &Context,
28    package: ObjectID,
29    module: &str,
30    name: &str,
31) -> Result<SuiMoveNormalizedFunction, RpcError<Error>> {
32    use Error as E;
33
34    if !Identifier::is_valid(module) {
35        return Err(invalid_params(E::BadIdentifier(module.to_owned())));
36    }
37
38    if !Identifier::is_valid(name) {
39        return Err(invalid_params(E::BadIdentifier(name.to_owned())));
40    }
41
42    let sig = ctx
43        .package_resolver()
44        .function_signature(*package, module, name)
45        .await
46        .map_err(|e| {
47            use sui_package_resolver::error::Error as PRE;
48            match &e {
49                // These errors can be triggered by passing a type that doesn't exist for the
50                // dynamic field name.
51                PRE::NotAPackage(_)
52                | PRE::PackageNotFound(_)
53                | PRE::ModuleNotFound(_, _)
54                | PRE::FunctionNotFound(_, _, _) => invalid_params(E::NotFound(e)),
55
56                // These errors can be triggered by requesting a type whose layout is too large
57                // (requires too may resources to resolve)
58                PRE::TooManyTypeNodes(_, _)
59                | PRE::TooManyTypeParams(_, _)
60                | PRE::TypeParamNesting(_, _) => invalid_params(E::ResolutionLimit(e)),
61
62                // The other errors are a form of internal error.
63                PRE::Bcs(_)
64                | PRE::Store { .. }
65                | PRE::DatatypeNotFound(_, _, _)
66                | PRE::Deserialize(_)
67                | PRE::EmptyPackage(_)
68                | PRE::LinkageNotFound(_)
69                | PRE::NoTypeOrigin(_, _, _)
70                | PRE::NotAnIdentifier(_)
71                | PRE::TypeArityMismatch(_, _)
72                | PRE::TypeParamOOB(_, _)
73                | PRE::UnexpectedReference
74                | PRE::UnexpectedSigner
75                | PRE::UnexpectedError(_)
76                | PRE::ValueNesting(_) => {
77                    RpcError::from(anyhow!(e).context("Failed to resolve type layout"))
78                }
79            }
80        })?;
81
82    Ok(normalized_function(&sig))
83}
84
85fn normalized_function(sig: &FunctionDef) -> SuiMoveNormalizedFunction {
86    SuiMoveNormalizedFunction {
87        visibility: visibility(sig.visibility),
88        is_entry: sig.is_entry,
89        type_parameters: sig.type_params.iter().map(|a| ability_set(*a)).collect(),
90        parameters: sig.parameters.iter().map(normalized_signature).collect(),
91        return_: sig.return_.iter().map(normalized_signature).collect(),
92    }
93}
94
95fn normalized_signature(sig: &OpenSignature) -> SuiMoveNormalizedType {
96    use SuiMoveNormalizedType as T;
97
98    let body = normalized_type(&sig.body);
99    match sig.ref_ {
100        Some(Reference::Immutable) => T::Reference(Box::new(body)),
101        Some(Reference::Mutable) => T::MutableReference(Box::new(body)),
102        None => body,
103    }
104}
105
106fn normalized_type(sig: &OpenSignatureBody) -> SuiMoveNormalizedType {
107    use OpenSignatureBody as S;
108    use SuiMoveNormalizedType as T;
109    match sig {
110        S::Address => T::Address,
111        S::Bool => T::Bool,
112        S::U8 => T::U8,
113        S::U16 => T::U16,
114        S::U32 => T::U32,
115        S::U64 => T::U64,
116        S::U128 => T::U128,
117        S::U256 => T::U256,
118        S::Vector(sig) => T::Vector(Box::new(normalized_type(sig))),
119        S::Datatype(t, params) => T::new_struct(
120            t.package.to_canonical_string(/* with_prefix */ true),
121            t.module.to_string(),
122            t.name.to_string(),
123            params.iter().map(normalized_type).collect(),
124        ),
125        S::TypeParameter(ix) => T::TypeParameter(*ix),
126    }
127}
128
129fn visibility(v: Visibility) -> SuiMoveVisibility {
130    match v {
131        Visibility::Public => SuiMoveVisibility::Public,
132        Visibility::Friend => SuiMoveVisibility::Friend,
133        Visibility::Private => SuiMoveVisibility::Private,
134    }
135}
136
137fn ability_set(a: AbilitySet) -> SuiMoveAbilitySet {
138    SuiMoveAbilitySet {
139        abilities: a.into_iter().map(ability).collect(),
140    }
141}
142
143fn ability(a: Ability) -> SuiMoveAbility {
144    match a {
145        Ability::Copy => SuiMoveAbility::Copy,
146        Ability::Drop => SuiMoveAbility::Drop,
147        Ability::Store => SuiMoveAbility::Store,
148        Ability::Key => SuiMoveAbility::Key,
149    }
150}