diff --git a/abi/resolver/src/lib.rs b/abi/resolver/src/lib.rs index 0b18d347d4..c76bf78b5d 100644 --- a/abi/resolver/src/lib.rs +++ b/abi/resolver/src/lib.rs @@ -165,6 +165,27 @@ impl<'a> ABIResolver<'a> { } }) } + + pub fn resolve_module_function_index( + &self, + module_id: &ModuleId, + function_idx: u16, + ) -> Result { + let module = self + .resolver + .get_module(module_id.address(), module_id.name())?; + if function_idx as usize >= module.function_defs.len() { + return Err(anyhow!( + "Function index {} out of range in {:?}", + function_idx, + module.self_id(), + )); + } + let function_def = module.function_def_at(FunctionDefinitionIndex::new(function_idx)); + let (func_name, func) = Function::new(&module, function_def); + self.function_to_abi(module_id, &func_name, &func) + } + pub fn resolve_function( &self, module_id: &ModuleId, @@ -417,7 +438,7 @@ mod tests { let test_source = r#" module {{sender}}::TestModule { struct A has copy, store{ - } + } struct B has key{ a: vector, } diff --git a/rpc/api/src/contract_api.rs b/rpc/api/src/contract_api.rs index b54229a17e..c0ecdb330b 100644 --- a/rpc/api/src/contract_api.rs +++ b/rpc/api/src/contract_api.rs @@ -46,6 +46,12 @@ pub trait ContractApi { #[rpc(name = "contract.resolve_function")] fn resolve_function(&self, function_id: FunctionIdView) -> FutureResult; + #[rpc(name = "contract.resolve_module_function_index")] + fn resolve_module_function_index( + &self, + module_id: ModuleIdView, + function_index: u16, + ) -> FutureResult; #[rpc(name = "contract.resolve_struct")] fn resolve_struct(&self, struct_tag: StructTagView) -> FutureResult; #[rpc(name = "contract.resolve_module")] diff --git a/rpc/server/src/module/contract_rpc.rs b/rpc/server/src/module/contract_rpc.rs index 8df3f7ef7e..9afaf82d5a 100644 --- a/rpc/server/src/module/contract_rpc.rs +++ b/rpc/server/src/module/contract_rpc.rs @@ -236,6 +236,21 @@ where Box::pin(fut.boxed()) } + fn resolve_module_function_index( + &self, + module_id: ModuleIdView, + function_idx: u16, + ) -> FutureResult { + let service = self.chain_state.clone(); + let storage = self.storage.clone(); + let fut = async move { + let state = ChainStateDB::new(storage, Some(service.state_root().await?)); + ABIResolver::new(&state).resolve_module_function_index(&module_id.0, function_idx) + } + .map_err(map_err); + Box::pin(fut.boxed()) + } + fn resolve_struct(&self, struct_tag: StructTagView) -> FutureResult { let service = self.chain_state.clone(); let storage = self.storage.clone();