mirror of
https://github.com/FuelLabs/sway.git
synced 2025-08-04 18:58:20 +00:00
feat: forc-call inline abi support (#7270)
Some checks failed
CI / forc-fmt-check-panic (push) Has been cancelled
CI / forc-fmt-check-sway-lib-std (push) Has been cancelled
CI / forc-fmt-check-sway-examples (push) Has been cancelled
CI / cargo-fmt-check (push) Has been cancelled
Codspeed Benchmarks / benchmarks (push) Has been cancelled
CI / build-reference-examples (push) Has been cancelled
CI / check-dependency-version-formats (push) Has been cancelled
CI / check-forc-manifest-version (push) Has been cancelled
CI / get-fuel-core-version (push) Has been cancelled
CI / build-sway-lib-std (push) Has been cancelled
CI / build-sway-examples (push) Has been cancelled
CI / check-sdk-harness-test-suite-compatibility (push) Has been cancelled
CI / build-mdbook (push) Has been cancelled
CI / build-forc-doc-sway-lib-std (push) Has been cancelled
CI / build-forc-test-project (push) Has been cancelled
CI / cargo-build-workspace (push) Has been cancelled
CI / cargo-clippy (push) Has been cancelled
CI / cargo-toml-fmt-check (push) Has been cancelled
CI / cargo-run-e2e-test-evm (push) Has been cancelled
CI / cargo-test-lib-std (push) Has been cancelled
CI / forc-run-benchmarks (push) Has been cancelled
CI / forc-unit-tests (push) Has been cancelled
CI / forc-pkg-fuels-deps-check (push) Has been cancelled
CI / cargo-test-sway-lsp (push) Has been cancelled
CI / cargo-test-forc (push) Has been cancelled
CI / cargo-test-workspace (push) Has been cancelled
CI / cargo-unused-deps-check (push) Has been cancelled
CI / pre-publish-check (push) Has been cancelled
github pages / deploy (push) Has been cancelled
CI / verifications-complete (push) Has been cancelled
CI / cargo-run-e2e-test (push) Has been cancelled
CI / cargo-run-e2e-test-release (push) Has been cancelled
CI / cargo-test-forc-debug (push) Has been cancelled
CI / cargo-test-forc-client (push) Has been cancelled
CI / cargo-test-forc-node (push) Has been cancelled
CI / notify-slack-on-failure (push) Has been cancelled
CI / publish (push) Has been cancelled
CI / publish-sway-lib-std (push) Has been cancelled
CI / Build and upload forc binaries to release (push) Has been cancelled
Some checks failed
CI / forc-fmt-check-panic (push) Has been cancelled
CI / forc-fmt-check-sway-lib-std (push) Has been cancelled
CI / forc-fmt-check-sway-examples (push) Has been cancelled
CI / cargo-fmt-check (push) Has been cancelled
Codspeed Benchmarks / benchmarks (push) Has been cancelled
CI / build-reference-examples (push) Has been cancelled
CI / check-dependency-version-formats (push) Has been cancelled
CI / check-forc-manifest-version (push) Has been cancelled
CI / get-fuel-core-version (push) Has been cancelled
CI / build-sway-lib-std (push) Has been cancelled
CI / build-sway-examples (push) Has been cancelled
CI / check-sdk-harness-test-suite-compatibility (push) Has been cancelled
CI / build-mdbook (push) Has been cancelled
CI / build-forc-doc-sway-lib-std (push) Has been cancelled
CI / build-forc-test-project (push) Has been cancelled
CI / cargo-build-workspace (push) Has been cancelled
CI / cargo-clippy (push) Has been cancelled
CI / cargo-toml-fmt-check (push) Has been cancelled
CI / cargo-run-e2e-test-evm (push) Has been cancelled
CI / cargo-test-lib-std (push) Has been cancelled
CI / forc-run-benchmarks (push) Has been cancelled
CI / forc-unit-tests (push) Has been cancelled
CI / forc-pkg-fuels-deps-check (push) Has been cancelled
CI / cargo-test-sway-lsp (push) Has been cancelled
CI / cargo-test-forc (push) Has been cancelled
CI / cargo-test-workspace (push) Has been cancelled
CI / cargo-unused-deps-check (push) Has been cancelled
CI / pre-publish-check (push) Has been cancelled
github pages / deploy (push) Has been cancelled
CI / verifications-complete (push) Has been cancelled
CI / cargo-run-e2e-test (push) Has been cancelled
CI / cargo-run-e2e-test-release (push) Has been cancelled
CI / cargo-test-forc-debug (push) Has been cancelled
CI / cargo-test-forc-client (push) Has been cancelled
CI / cargo-test-forc-node (push) Has been cancelled
CI / notify-slack-on-failure (push) Has been cancelled
CI / publish (push) Has been cancelled
CI / publish-sway-lib-std (push) Has been cancelled
CI / Build and upload forc binaries to release (push) Has been cancelled
## Description This pull request introduces a enhancement to the ABI handling in the `forc-client` plugin by replacing the `Either<PathBuf, Url>` type with a new `AbiSource` enum. This improves flexibility and usability by supporting ABI sources as file paths, URLs, or raw JSON strings. Additionally, it simplifies related code and updates documentation and tests accordingly. This represents an additional optional for callers to use forc-call with an ABI available at-hand without needing to write to a file first. ## Checklist - [ ] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [ ] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [ ] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: z <zees-dev@users.noreply.github.com>
This commit is contained in:
parent
de2a5ac0f0
commit
b54fce7727
4 changed files with 145 additions and 72 deletions
|
@ -1,6 +1,5 @@
|
|||
use crate::NodeTarget;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use either::Either;
|
||||
use fuel_crypto::SecretKey;
|
||||
use fuels::programs::calls::CallParameters;
|
||||
use fuels_core::types::{Address, AssetId, ContractId};
|
||||
|
@ -138,19 +137,64 @@ impl From<CallParametersOpts> for CallParameters {
|
|||
}
|
||||
|
||||
/// Operation for the call command
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum AbiSource {
|
||||
/// ABI from file path
|
||||
File(PathBuf),
|
||||
/// ABI from URL
|
||||
Url(Url),
|
||||
/// ABI as raw string
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AbiSource {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AbiSource::File(path) => write!(f, "{}", path.display()),
|
||||
AbiSource::Url(url) => write!(f, "{}", url),
|
||||
AbiSource::String(s) => write!(f, "{}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for AbiSource {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
// First try to parse as URL
|
||||
if let Ok(url) = Url::parse(&s) {
|
||||
match url.scheme() {
|
||||
"http" | "https" | "ipfs" => return Ok(AbiSource::Url(url)),
|
||||
_ => {} // Continue to check other options
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it looks like a JSON string (starts with '{' or '[')
|
||||
let trimmed = s.trim();
|
||||
if (trimmed.starts_with('{') && trimmed.ends_with('}'))
|
||||
|| (trimmed.starts_with('[') && trimmed.ends_with(']'))
|
||||
{
|
||||
return Ok(AbiSource::String(s));
|
||||
}
|
||||
|
||||
// Default to treating as file path
|
||||
Ok(AbiSource::File(PathBuf::from(s)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Operation {
|
||||
/// Call a specific contract function
|
||||
CallFunction {
|
||||
contract_id: ContractId,
|
||||
abi: Either<PathBuf, Url>,
|
||||
abi: AbiSource,
|
||||
function: FuncType,
|
||||
function_args: Vec<String>,
|
||||
},
|
||||
/// List all functions in the contract
|
||||
ListFunctions {
|
||||
contract_id: ContractId,
|
||||
abi: Either<PathBuf, Url>,
|
||||
abi: AbiSource,
|
||||
},
|
||||
/// Direct transfer of assets to a contract
|
||||
DirectTransfer {
|
||||
|
@ -269,6 +313,13 @@ forc call 0x0dcba78d7b09a1f77353f51367afd8b8ab94b5b2bb6c9437d9ba9eea47dede97 \
|
|||
--list-functions
|
||||
```
|
||||
|
||||
### Call a contract with inline ABI JSON string
|
||||
```sh
|
||||
forc call 0x0dcba78d7b09a1f77353f51367afd8b8ab94b5b2bb6c9437d9ba9eea47dede97 \
|
||||
--abi '{"functions":[{"inputs":[],"name":"get_balance","output":{"name":"","type":"u64","typeArguments":null}}]}' \
|
||||
get_balance
|
||||
```
|
||||
|
||||
### Direct transfer of asset to a contract or address
|
||||
```sh
|
||||
forc call 0x0dcba78d7b09a1f77353f51367afd8b8ab94b5b2bb6c9437d9ba9eea47dede97 \
|
||||
|
@ -281,17 +332,18 @@ pub struct Command {
|
|||
#[clap(help_heading = "CONTRACT")]
|
||||
pub address: Address,
|
||||
|
||||
/// Path or URI to a JSON ABI file
|
||||
/// Path, URI, or raw JSON string for the ABI
|
||||
/// Required when making function calls or listing functions
|
||||
#[clap(long, value_parser = parse_abi_path)]
|
||||
pub abi: Option<Either<PathBuf, Url>>,
|
||||
/// Can be a file path, HTTP/HTTPS URL, or raw JSON string
|
||||
#[clap(long, value_parser = |s: &str| AbiSource::try_from(s.to_string()))]
|
||||
pub abi: Option<AbiSource>,
|
||||
|
||||
/// Additional contract IDs and their ABI paths for better tracing and debugging.
|
||||
/// Format: contract_id:abi_path (can be used multiple times)
|
||||
/// Example: --contract-abi 0x123:./abi1.json --contract-abi 0x456:https://example.com/abi2.json
|
||||
/// Contract IDs can be provided with or without 0x prefix
|
||||
#[clap(long = "contract-abi", value_parser = parse_contract_abi, action = clap::ArgAction::Append, help_heading = "CONTRACT")]
|
||||
pub contract_abis: Option<Vec<(ContractId, Either<PathBuf, Url>)>>,
|
||||
pub contract_abis: Option<Vec<(ContractId, AbiSource)>>,
|
||||
|
||||
/// Label addresses in the trace output for better readability.
|
||||
/// Format: address:label (can be used multiple times)
|
||||
|
@ -404,18 +456,7 @@ impl Command {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_abi_path(s: &str) -> Result<Either<PathBuf, Url>, String> {
|
||||
if let Ok(url) = Url::parse(s) {
|
||||
match url.scheme() {
|
||||
"http" | "https" | "ipfs" => Ok(Either::Right(url)),
|
||||
_ => Err(format!("Unsupported URL scheme: {}", url.scheme())),
|
||||
}
|
||||
} else {
|
||||
Ok(Either::Left(PathBuf::from(s)))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_contract_abi(s: &str) -> Result<(ContractId, Either<PathBuf, Url>), String> {
|
||||
fn parse_contract_abi(s: &str) -> Result<(ContractId, AbiSource), String> {
|
||||
let parts: Vec<&str> = s.trim().split(':').collect();
|
||||
let [contract_id_str, abi_path_str] = parts.try_into().map_err(|_| {
|
||||
format!(
|
||||
|
@ -428,7 +469,7 @@ fn parse_contract_abi(s: &str) -> Result<(ContractId, Either<PathBuf, Url>), Str
|
|||
ContractId::from_str(&format!("0x{}", contract_id_str.trim_start_matches("0x")))
|
||||
.map_err(|e| format!("Invalid contract ID '{}': {}", contract_id_str, e))?;
|
||||
|
||||
let abi_path = parse_abi_path(abi_path_str)
|
||||
let abi_path = AbiSource::try_from(abi_path_str.to_string())
|
||||
.map_err(|e| format!("Invalid ABI path '{}': {}", abi_path_str, e))?;
|
||||
|
||||
Ok((contract_id, abi_path))
|
||||
|
@ -449,3 +490,26 @@ fn parse_label(s: &str) -> Result<(ContractId, String), String> {
|
|||
|
||||
Ok((contract_id, label.to_string()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_abi_source_try_from() {
|
||||
let url_result = AbiSource::try_from("https://example.com/abi.json".to_string()).unwrap();
|
||||
assert!(matches!(url_result, AbiSource::Url(_)));
|
||||
|
||||
let json_result = AbiSource::try_from(r#"{"functions": []}"#.to_string()).unwrap();
|
||||
assert!(matches!(json_result, AbiSource::String(_)));
|
||||
|
||||
let array_result = AbiSource::try_from("[]".to_string()).unwrap();
|
||||
assert!(matches!(array_result, AbiSource::String(_)));
|
||||
|
||||
let file_result = AbiSource::try_from("./contract-abi.json".to_string()).unwrap();
|
||||
assert!(matches!(file_result, AbiSource::File(_)));
|
||||
|
||||
let file_url_result = AbiSource::try_from("file:///path/to/abi.json".to_string()).unwrap();
|
||||
assert!(matches!(file_url_result, AbiSource::File(_)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
missing_contracts::determine_missing_contracts,
|
||||
parser::{param_type_val_to_token, token_to_string},
|
||||
trace::interpret_execution_trace,
|
||||
CallResponse, Either,
|
||||
CallResponse,
|
||||
},
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
|
@ -32,13 +32,12 @@ use fuels_core::{
|
|||
ContractId,
|
||||
},
|
||||
};
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
use url::Url;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Calls a contract function with the given parameters
|
||||
pub async fn call_function(
|
||||
contract_id: ContractId,
|
||||
abi: Either<PathBuf, Url>,
|
||||
abi: crate::cmd::call::AbiSource,
|
||||
function: FuncType,
|
||||
function_args: Vec<String>,
|
||||
cmd: cmd::Call,
|
||||
|
@ -397,6 +396,7 @@ pub mod tests {
|
|||
op::call::{call, get_wallet, PrivateKeySigner},
|
||||
};
|
||||
use fuels::{crypto::SecretKey, prelude::*};
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn get_contract_call_cmd(
|
||||
id: ContractId,
|
||||
|
@ -407,7 +407,7 @@ pub mod tests {
|
|||
) -> cmd::Call {
|
||||
cmd::Call {
|
||||
address: (*id).into(),
|
||||
abi: Some(Either::Left(std::path::PathBuf::from(
|
||||
abi: Some(cmd::call::AbiSource::File(PathBuf::from(
|
||||
"../../forc-plugins/forc-client/test/data/contract_with_types/contract_with_types-abi.json",
|
||||
))),
|
||||
function: Some(selector.to_string()),
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use crate::op::call::{
|
||||
parser::{get_default_value, param_to_function_arg, param_type_val_to_token, token_to_string},
|
||||
Abi,
|
||||
use crate::{
|
||||
cmd::call::AbiSource,
|
||||
op::call::{
|
||||
parser::{
|
||||
get_default_value, param_to_function_arg, param_type_val_to_token, token_to_string,
|
||||
},
|
||||
Abi,
|
||||
},
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use fuels_core::types::{param_types::ParamType, ContractId};
|
||||
|
@ -17,12 +22,7 @@ pub fn list_contract_functions<W: Write>(
|
|||
) -> Result<()> {
|
||||
// First, list functions for the main contract
|
||||
if let Some(main_abi) = abi_map.get(main_contract_id) {
|
||||
list_functions_for_single_contract(
|
||||
main_contract_id,
|
||||
main_abi,
|
||||
true, // is_main_contract
|
||||
writer,
|
||||
)?;
|
||||
list_functions_for_single_contract(main_contract_id, main_abi, true, writer)?;
|
||||
} else {
|
||||
return Err(anyhow!("Main contract ABI not found in abi_map"));
|
||||
}
|
||||
|
@ -38,12 +38,7 @@ pub fn list_contract_functions<W: Write>(
|
|||
writeln!(writer, "Additional Contracts:\n")?;
|
||||
|
||||
for (contract_id, abi) in additional_contracts {
|
||||
list_functions_for_single_contract(
|
||||
contract_id,
|
||||
abi,
|
||||
false, // is_main_contract
|
||||
writer,
|
||||
)?;
|
||||
list_functions_for_single_contract(contract_id, abi, false, writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,20 +128,29 @@ fn list_functions_for_single_contract<W: Write>(
|
|||
)
|
||||
})?;
|
||||
|
||||
// Since we don't know the original ABI path, we'll use a placeholder
|
||||
let abi_placeholder = "./contract-abi.json";
|
||||
|
||||
let painted_name = forc_util::ansiterm::Colour::Blue.paint(func.name.clone());
|
||||
writeln!(
|
||||
writer,
|
||||
"{}({}) -> {}",
|
||||
painted_name, func_args_types, return_type
|
||||
)?;
|
||||
writeln!(
|
||||
writer,
|
||||
" forc call \\\n --abi {} \\\n {} \\\n {} {}\n",
|
||||
abi_placeholder, contract_id, func.name, func_args_inputs,
|
||||
)?;
|
||||
match &abi.source {
|
||||
AbiSource::String(s) => {
|
||||
// json string in quotes for shell
|
||||
writeln!(
|
||||
writer,
|
||||
" forc call \\\n --abi \"{}\" \\\n {} \\\n {} {}\n",
|
||||
s, contract_id, func.name, func_args_inputs,
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
writeln!(
|
||||
writer,
|
||||
" forc call \\\n --abi {} \\\n {} \\\n {} {}\n",
|
||||
abi.source, contract_id, func.name, func_args_inputs,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -184,24 +188,21 @@ mod tests {
|
|||
let output_bytes = output.into_inner();
|
||||
let output_string = String::from_utf8(output_bytes).expect("Output was not valid UTF-8");
|
||||
|
||||
// Verify the output contains expected function names and formatting
|
||||
// Check that the output contains key elements instead of exact string match
|
||||
assert!(output_string.contains("Callable functions for contract:"));
|
||||
|
||||
assert!(output_string.contains(
|
||||
"\u{1b}[34mtest_struct_with_generic\u{1b}[0m(a: GenericStruct) -> GenericStruct"
|
||||
));
|
||||
assert!(output_string.contains("forc call \\"));
|
||||
assert!(output_string.contains("--abi ./contract-abi.json \\"));
|
||||
assert!(output_string.contains(format!("{id} \\").as_str()));
|
||||
assert!(output_string.contains("test_struct_with_generic \"{0, aaaa}\""));
|
||||
|
||||
assert!(output_string
|
||||
.contains("\u{1b}[34mtest_complex_struct\u{1b}[0m(a: ComplexStruct) -> ComplexStruct"));
|
||||
assert!(output_string.contains("forc call \\"));
|
||||
assert!(output_string.contains("--abi ./contract-abi.json \\"));
|
||||
assert!(output_string.contains(format!("{id} \\").as_str()));
|
||||
assert!(output_string.contains(
|
||||
"test_complex_struct \"{({aa, 0}, 0), (Active:false), 0, {{0, aaaa}, aaaa}}\""
|
||||
));
|
||||
.contains("053efe51968252f029899660d7064124084a48136e326e467f62cb7f5913ba77"));
|
||||
assert!(output_string.contains("forc call"));
|
||||
assert!(output_string.contains("programType"));
|
||||
assert!(output_string.contains("contract"));
|
||||
assert!(output_string.contains("functions"));
|
||||
|
||||
// Verify that we have some function names
|
||||
assert!(output_string.contains("test_"));
|
||||
assert!(output_string.contains("transfer"));
|
||||
|
||||
// Verify ABI structure is present
|
||||
assert!(output_string.contains("concreteTypes"));
|
||||
assert!(output_string.contains("metadataTypes"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ mod parser;
|
|||
mod trace;
|
||||
mod transfer;
|
||||
|
||||
use crate::cmd::call::AbiSource;
|
||||
use crate::{
|
||||
cmd,
|
||||
constants::DEFAULT_PRIVATE_KEY,
|
||||
|
@ -15,7 +16,6 @@ use crate::{
|
|||
util::tx::{prompt_forc_wallet_password, select_local_wallet_account},
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use either::Either;
|
||||
use fuel_abi_types::abi::{
|
||||
program::ProgramABI,
|
||||
unified_program::{UnifiedProgramABI, UnifiedTypeDeclaration},
|
||||
|
@ -126,12 +126,12 @@ async fn setup_connection(
|
|||
Ok((wallet, tx_policies, *base_asset_id))
|
||||
}
|
||||
|
||||
/// Helper function to load ABI from file or URL
|
||||
async fn load_abi(abi: &Either<std::path::PathBuf, url::Url>) -> anyhow::Result<String> {
|
||||
/// Helper function to load ABI from file, URL, or raw string
|
||||
async fn load_abi(abi: &AbiSource) -> anyhow::Result<String> {
|
||||
match abi {
|
||||
Either::Left(path) => std::fs::read_to_string(path)
|
||||
AbiSource::File(path) => std::fs::read_to_string(path)
|
||||
.map_err(|e| anyhow!("Failed to read ABI file at {:?}: {}", path, e)),
|
||||
Either::Right(url) => {
|
||||
AbiSource::Url(url) => {
|
||||
let response = reqwest::get(url.clone())
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to fetch ABI from URL {}: {}", url, e))?;
|
||||
|
@ -142,6 +142,12 @@ async fn load_abi(abi: &Either<std::path::PathBuf, url::Url>) -> anyhow::Result<
|
|||
String::from_utf8(bytes.to_vec())
|
||||
.map_err(|e| anyhow!("Failed to parse response as UTF-8 from URL {}: {}", url, e))
|
||||
}
|
||||
AbiSource::String(json_str) => {
|
||||
// Validate that it's valid JSON
|
||||
serde_json::from_str::<serde_json::Value>(json_str)
|
||||
.map_err(|e| anyhow!("Invalid JSON in ABI string: {}", e))?;
|
||||
Ok(json_str.to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,6 +195,7 @@ async fn get_wallet(
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Abi {
|
||||
source: AbiSource,
|
||||
program: ProgramABI,
|
||||
unified: UnifiedProgramABI,
|
||||
// TODO: required for vm interpreter step through
|
||||
|
@ -213,6 +220,7 @@ impl FromStr for Abi {
|
|||
.collect::<HashMap<_, _>>();
|
||||
|
||||
Ok(Self {
|
||||
source: AbiSource::String(s.to_string()),
|
||||
program,
|
||||
unified,
|
||||
type_lookup,
|
||||
|
@ -310,8 +318,8 @@ pub(crate) fn display_detailed_call_info(
|
|||
/// This is a reusable function for both call_function and list_functions operations
|
||||
pub(crate) async fn create_abi_map(
|
||||
main_contract_id: ContractId,
|
||||
main_abi: &Either<std::path::PathBuf, url::Url>,
|
||||
additional_contract_abis: Option<Vec<(ContractId, Either<std::path::PathBuf, url::Url>)>>,
|
||||
main_abi: &AbiSource,
|
||||
additional_contract_abis: Option<Vec<(ContractId, AbiSource)>>,
|
||||
) -> anyhow::Result<HashMap<ContractId, Abi>> {
|
||||
// Load main ABI
|
||||
let main_abi_str = load_abi(main_abi).await?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue