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