From 2cfcf3170bc7a5b659e3ca6f1cb64a026c2fd0e8 Mon Sep 17 00:00:00 2001 From: Daniyar Itegulov Date: Thu, 20 Oct 2022 17:03:28 +1100 Subject: [PATCH] feat: populate metadata with build information (#55) --- Cargo.lock | 7 +- cargo-near/Cargo.toml | 5 +- cargo-near/src/abi.rs | 2 + cargo-near/src/build.rs | 33 ++++-- integration-tests/Cargo.toml | 2 +- integration-tests/templates/_Cargo.toml | 2 +- .../sdk-dependency/_Cargo_explicit.toml | 2 + .../_Cargo_multiple_features.toml | 2 +- .../_Cargo_no_default_features.toml | 2 +- .../sdk-dependency/_Cargo_patch.toml | 2 +- .../_Cargo_platform_specific.toml | 4 +- .../sdk-dependency/_Cargo_renamed.toml | 2 +- integration-tests/tests/abi/borsh_schema.rs | 100 ++++++++-------- integration-tests/tests/abi/callbacks.rs | 32 ++--- integration-tests/tests/abi/e2e.rs | 22 ++-- integration-tests/tests/abi/json_schema.rs | 110 +++++++++--------- integration-tests/tests/build/embed.rs | 6 +- integration-tests/tests/build/mod.rs | 2 +- integration-tests/tests/build/opts.rs | 4 +- integration-tests/tests/cargo/mod.rs | 30 +++-- integration-tests/tests/lib.rs | 1 + integration-tests/tests/{build => }/util.rs | 29 +++++ 22 files changed, 228 insertions(+), 173 deletions(-) rename integration-tests/tests/{build => }/util.rs (51%) diff --git a/Cargo.lock b/Cargo.lock index e459ffaa..3b825012 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -473,6 +473,7 @@ name = "cargo-near" version = "0.2.0" dependencies = [ "anyhow", + "bs58", "camino", "cargo_metadata", "clap", @@ -481,8 +482,10 @@ dependencies = [ "libloading", "log", "near-abi", + "rustc_version", "schemars", "serde_json", + "sha2 0.10.3", "symbolic-debuginfo", "zstd", ] @@ -1611,9 +1614,9 @@ dependencies = [ [[package]] name = "near-abi" -version = "0.1.0-pre.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5281adc3a63d798b0e35683dee66095cbb94e431960ec859d5a8397b093f39" +checksum = "85f9816032a8688b52e2e0e51e1a5513e7e05310eb2eebe1d913fcf82be1e1d7" dependencies = [ "borsh", "schemars", diff --git a/cargo-near/Cargo.toml b/cargo-near/Cargo.toml index cc945a8d..bc4a77d8 100644 --- a/cargo-near/Cargo.toml +++ b/cargo-near/Cargo.toml @@ -13,15 +13,18 @@ categories = ["development-tools", "development-tools::cargo-plugins", "developm [dependencies] anyhow = "1.0" +bs58 = "0.4" camino = "1.1.1" cargo_metadata = "0.14" clap = { version = "3.2", features = ["derive", "env"] } colored = "2.0" env_logger = "0.9" log = "0.4" +rustc_version = "0.4" serde_json = "1.0" +sha2 = "0.10" symbolic-debuginfo = "8.8" schemars = "0.8" -near-abi = { version = "0.1.0-pre.0", features = ["__chunked-entries"] } +near-abi = { version = "0.2.0", features = ["__chunked-entries"] } libloading = "0.7.3" zstd = "0.11" diff --git a/cargo-near/src/abi.rs b/cargo-near/src/abi.rs index 7205f20f..c5d71a29 100644 --- a/cargo-near/src/abi.rs +++ b/cargo-near/src/abi.rs @@ -146,6 +146,8 @@ fn extract_metadata(crate_metadata: &CrateMetadata) -> near_abi::AbiMetadata { name: Some(package.name.clone()), version: Some(package.version.to_string()), authors: package.authors.clone(), + build: None, + wasm_hash: None, other: HashMap::new(), } } diff --git a/cargo-near/src/build.rs b/cargo-near/src/build.rs index 3fae23c7..306eafb4 100644 --- a/cargo-near/src/build.rs +++ b/cargo-near/src/build.rs @@ -2,6 +2,8 @@ use crate::abi::{AbiCompression, AbiFormat, AbiResult}; use crate::cargo::{manifest::CargoManifestPath, metadata::CrateMetadata}; use crate::{abi, util, BuildCommand}; use colored::Colorize; +use near_abi::BuildInfo; +use sha2::{Digest, Sha256}; use std::io::BufRead; const COMPILATION_TARGET: &str = "wasm32-unknown-unknown"; @@ -35,18 +37,15 @@ pub(crate) fn run(args: BuildCommand) -> anyhow::Result<()> { cargo_args.push("--release"); } - let mut pretty_abi_path = None; + let mut abi = None; let mut min_abi_path = None; if !args.no_abi { - let contract_abi = abi::generate_abi(&crate_metadata, args.doc, true)?; - let AbiResult { path } = abi::write_to_file( - &contract_abi, - &crate_metadata, - AbiFormat::Json, - AbiCompression::NoOp, - )?; - pretty_abi_path.replace(util::copy(&path, &out_dir)?); - + let mut contract_abi = abi::generate_abi(&crate_metadata, args.doc, true)?; + contract_abi.metadata.build = Some(BuildInfo { + compiler: format!("rustc {}", rustc_version::version()?), + builder: format!("cargo-near {}", env!("CARGO_PKG_VERSION")), + image: None, + }); if args.embed_abi { let path = util::handle_step("Compressing ABI to be embedded..", || { let AbiResult { path } = abi::write_to_file( @@ -59,6 +58,7 @@ pub(crate) fn run(args: BuildCommand) -> anyhow::Result<()> { })?; min_abi_path.replace(util::copy(&path, &out_dir)?); } + abi = Some(contract_abi); } if let (true, Some(abi_path)) = (args.embed_abi, &min_abi_path) { @@ -82,8 +82,17 @@ pub(crate) fn run(args: BuildCommand) -> anyhow::Result<()> { "Binary", wasm_artifact.path.to_string().bright_yellow().bold(), )]; - if let Some(abi_path) = pretty_abi_path { - messages.push(("ABI", abi_path.to_string().yellow().bold())); + if let Some(mut abi) = abi { + let mut hasher = Sha256::new(); + hasher.update(std::fs::read(&wasm_artifact.path)?); + let hash = hasher.finalize(); + let hash = bs58::encode(hash).into_string(); + abi.metadata.wasm_hash = Some(hash); + + let AbiResult { path } = + abi::write_to_file(&abi, &crate_metadata, AbiFormat::Json, AbiCompression::NoOp)?; + let pretty_abi_path = util::copy(&path, &out_dir)?; + messages.push(("ABI", pretty_abi_path.to_string().yellow().bold())); } if let Some(abi_path) = min_abi_path { messages.push(("Embedded ABI", abi_path.to_string().yellow().bold())); diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 8f03df68..e2695931 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -near-abi = "0.1.0-pre.0" +near-abi = "0.2.0" [dev-dependencies] anyhow = "1.0" diff --git a/integration-tests/templates/_Cargo.toml b/integration-tests/templates/_Cargo.toml index 8867a0a4..e08227fe 100644 --- a/integration-tests/templates/_Cargo.toml +++ b/integration-tests/templates/_Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -near-sdk = { version = "4.1.0-pre.3", features = ["abi"] } +near-sdk = { version = "4.1.0-pre.3", features = ["abi"], git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } serde = { version = "1", features = ["derive"] } schemars = "0.8" diff --git a/integration-tests/templates/sdk-dependency/_Cargo_explicit.toml b/integration-tests/templates/sdk-dependency/_Cargo_explicit.toml index 265bcb52..66e6b9c5 100644 --- a/integration-tests/templates/sdk-dependency/_Cargo_explicit.toml +++ b/integration-tests/templates/sdk-dependency/_Cargo_explicit.toml @@ -13,6 +13,8 @@ schemars = "0.8" [dependencies.near-sdk] version = "4.1.0-pre.3" features = ["abi"] +git = "https://github.com/near/near-sdk-rs.git" +rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" [workspace] members = [] diff --git a/integration-tests/templates/sdk-dependency/_Cargo_multiple_features.toml b/integration-tests/templates/sdk-dependency/_Cargo_multiple_features.toml index e8bcdfc3..ee1da173 100644 --- a/integration-tests/templates/sdk-dependency/_Cargo_multiple_features.toml +++ b/integration-tests/templates/sdk-dependency/_Cargo_multiple_features.toml @@ -7,7 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -near-sdk = { version = "4.1.0-pre.3", features = ["abi", "unstable"] } +near-sdk = { version = "4.1.0-pre.3", features = ["abi", "unstable"], git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } serde = { version = "1", features = ["derive"] } schemars = "0.8" diff --git a/integration-tests/templates/sdk-dependency/_Cargo_no_default_features.toml b/integration-tests/templates/sdk-dependency/_Cargo_no_default_features.toml index 4c369fe6..796930c4 100644 --- a/integration-tests/templates/sdk-dependency/_Cargo_no_default_features.toml +++ b/integration-tests/templates/sdk-dependency/_Cargo_no_default_features.toml @@ -7,7 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -near-sdk = { version = "4.1.0-pre.3", default-features = false, features = ["abi"] } +near-sdk = { version = "4.1.0-pre.3", default-features = false, features = ["abi"], git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } serde = { version = "1", features = ["derive"] } schemars = "0.8" diff --git a/integration-tests/templates/sdk-dependency/_Cargo_patch.toml b/integration-tests/templates/sdk-dependency/_Cargo_patch.toml index d8c8fe2e..bc38e661 100644 --- a/integration-tests/templates/sdk-dependency/_Cargo_patch.toml +++ b/integration-tests/templates/sdk-dependency/_Cargo_patch.toml @@ -12,7 +12,7 @@ serde = { version = "1", features = ["derive"] } schemars = "0.8" [patch.crates-io] -near-sdk = { git = "https://github.com/near/near-sdk-rs.git", rev = "792d5eb26d26a0878dbf59e304afa4e19540c317" } +near-sdk = { git = "https://github.com/near/near-sdk-rs.git", rev = "792d5eb26d26a0878dbf59e304afa4e19540c317", git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } [workspace] members = [] diff --git a/integration-tests/templates/sdk-dependency/_Cargo_platform_specific.toml b/integration-tests/templates/sdk-dependency/_Cargo_platform_specific.toml index 7b404b42..2065c7a9 100644 --- a/integration-tests/templates/sdk-dependency/_Cargo_platform_specific.toml +++ b/integration-tests/templates/sdk-dependency/_Cargo_platform_specific.toml @@ -11,10 +11,10 @@ serde = { version = "1", features = ["derive"] } schemars = "0.8" [target.'cfg(windows)'.dependencies] -near-sdk = { version = "4.1.0-pre.3", features = ["abi"] } +near-sdk = { version = "4.1.0-pre.3", features = ["abi"], git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } [target.'cfg(unix)'.dependencies] -near-sdk = { version = "4.1.0-pre.3", features = ["abi"] } +near-sdk = { version = "4.1.0-pre.3", features = ["abi"], git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } [workspace] members = [] diff --git a/integration-tests/templates/sdk-dependency/_Cargo_renamed.toml b/integration-tests/templates/sdk-dependency/_Cargo_renamed.toml index 5778af19..93d8ac74 100644 --- a/integration-tests/templates/sdk-dependency/_Cargo_renamed.toml +++ b/integration-tests/templates/sdk-dependency/_Cargo_renamed.toml @@ -11,7 +11,7 @@ serde = { version = "1", features = ["derive"] } schemars = "0.8" [dependencies.near] -near = { version = "4.1.0-pre.3", package = "near-sdk", features = ["abi"] } +near = { version = "4.1.0-pre.3", package = "near-sdk", features = ["abi"], git = "https://github.com/near/near-sdk-rs.git", rev = "6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b" } [workspace] members = [] diff --git a/integration-tests/tests/abi/borsh_schema.rs b/integration-tests/tests/abi/borsh_schema.rs index 74d00ca1..1ea26b51 100644 --- a/integration-tests/tests/abi/borsh_schema.rs +++ b/integration-tests/tests/abi/borsh_schema.rs @@ -1,23 +1,9 @@ +use crate::util::AsBorshSchema; use borsh::schema::{BorshSchemaContainer, Definition, Fields}; use cargo_near_integration_tests::{generate_abi, generate_abi_fn}; use function_name::named; -use near_abi::{AbiParameter, AbiType}; use std::collections::HashMap; -trait AsBorshSchema { - fn borsh_schema(&self) -> anyhow::Result<&BorshSchemaContainer>; -} - -impl AsBorshSchema for AbiParameter { - fn borsh_schema(&self) -> anyhow::Result<&BorshSchemaContainer> { - if let AbiType::Borsh { type_schema } = &self.typ { - Ok(type_schema) - } else { - anyhow::bail!("Expected Borsh serialization type, but got {:?}", self) - } - } -} - #[test] #[named] fn test_borsh_schema_numeric_primitives_signed() -> anyhow::Result<()> { @@ -34,7 +20,8 @@ fn test_borsh_schema_numeric_primitives_signed() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 5); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 5); let i8_schema = BorshSchemaContainer { declaration: "i8".to_string(), definitions: HashMap::new(), @@ -60,11 +47,11 @@ fn test_borsh_schema_numeric_primitives_signed() -> anyhow::Result<()> { // declaration: "i64".to_string(), // definitions: HashMap::new(), // }; - assert_eq!(function.params[0].borsh_schema()?, &i8_schema); - assert_eq!(function.params[1].borsh_schema()?, &i16_schema); - assert_eq!(function.params[2].borsh_schema()?, &i32_schema); - assert_eq!(function.params[3].borsh_schema()?, &i64_schema); - assert_eq!(function.params[4].borsh_schema()?, &i128_schema); + assert_eq!(¶ms[0].type_schema, &i8_schema); + assert_eq!(¶ms[1].type_schema, &i16_schema); + assert_eq!(¶ms[2].type_schema, &i32_schema); + assert_eq!(¶ms[3].type_schema, &i64_schema); + assert_eq!(¶ms[4].type_schema, &i128_schema); Ok(()) } @@ -85,7 +72,8 @@ fn test_borsh_schema_numeric_primitives_unsigned() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 5); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 5); let u8_schema = BorshSchemaContainer { declaration: "u8".to_string(), definitions: HashMap::new(), @@ -111,11 +99,11 @@ fn test_borsh_schema_numeric_primitives_unsigned() -> anyhow::Result<()> { // declaration: "u64".to_string(), // definitions: HashMap::new(), // }; - assert_eq!(function.params[0].borsh_schema()?, &u8_schema); - assert_eq!(function.params[1].borsh_schema()?, &u16_schema); - assert_eq!(function.params[2].borsh_schema()?, &u32_schema); - assert_eq!(function.params[3].borsh_schema()?, &u64_schema); - assert_eq!(function.params[4].borsh_schema()?, &u128_schema); + assert_eq!(¶ms[0].type_schema, &u8_schema); + assert_eq!(¶ms[1].type_schema, &u16_schema); + assert_eq!(¶ms[2].type_schema, &u32_schema); + assert_eq!(¶ms[3].type_schema, &u64_schema); + assert_eq!(¶ms[4].type_schema, &u128_schema); Ok(()) } @@ -129,7 +117,8 @@ fn test_borsh_schema_numeric_primitives_float() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 2); let f32_schema = BorshSchemaContainer { declaration: "f32".to_string(), definitions: HashMap::new(), @@ -138,8 +127,8 @@ fn test_borsh_schema_numeric_primitives_float() -> anyhow::Result<()> { declaration: "f64".to_string(), definitions: HashMap::new(), }; - assert_eq!(function.params[0].borsh_schema()?, &f32_schema); - assert_eq!(function.params[1].borsh_schema()?, &f64_schema); + assert_eq!(¶ms[0].type_schema, &f32_schema); + assert_eq!(¶ms[1].type_schema, &f64_schema); Ok(()) } @@ -153,14 +142,15 @@ fn test_borsh_schema_string() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 3); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 3); let string_schema = BorshSchemaContainer { declaration: "string".to_string(), definitions: HashMap::new(), }; - assert_eq!(function.params[0].borsh_schema()?, &string_schema); - assert_eq!(function.params[1].borsh_schema()?, &string_schema); - assert_eq!(function.params[2].borsh_schema()?, &string_schema); + assert_eq!(¶ms[0].type_schema, &string_schema); + assert_eq!(¶ms[1].type_schema, &string_schema); + assert_eq!(¶ms[2].type_schema, &string_schema); Ok(()) } @@ -174,7 +164,8 @@ fn test_borsh_schema_other_primitives() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 2); // char is unsupported by borsh spec // let char_schema = BorshSchemaContainer { // declaration: "char".to_string(), @@ -188,8 +179,8 @@ fn test_borsh_schema_other_primitives() -> anyhow::Result<()> { declaration: "nil".to_string(), definitions: HashMap::new(), }; - assert_eq!(function.params[0].borsh_schema()?, &bool_schema); - assert_eq!(function.params[1].borsh_schema()?, &unit_schema); + assert_eq!(¶ms[0].type_schema, &bool_schema); + assert_eq!(¶ms[1].type_schema, &unit_schema); Ok(()) } @@ -207,7 +198,8 @@ fn test_borsh_schema_tuples() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 2); // Needs https://github.com/near/borsh-rs/pull/100 to come in first // let tuple1_schema = BorshSchemaContainer { // declaration: "Tuple".to_string(), @@ -231,8 +223,8 @@ fn test_borsh_schema_tuples() -> anyhow::Result<()> { }, )]), }; - assert_eq!(function.params[0].borsh_schema()?, &tuple2_schema); - assert_eq!(function.params[1].borsh_schema()?, &tuple3_schema); + assert_eq!(¶ms[0].type_schema, &tuple2_schema); + assert_eq!(¶ms[1].type_schema, &tuple3_schema); Ok(()) } @@ -251,7 +243,8 @@ fn test_borsh_schema_arrays() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 3); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 3); let array8_schema = BorshSchemaContainer { declaration: "Array".to_string(), definitions: HashMap::from([( @@ -281,9 +274,9 @@ fn test_borsh_schema_arrays() -> anyhow::Result<()> { }, )]), }; - assert_eq!(function.params[0].borsh_schema()?, &array8_schema); - assert_eq!(function.params[1].borsh_schema()?, &array16_schema); - assert_eq!(function.params[2].borsh_schema()?, &array_unlim_schema); + assert_eq!(¶ms[0].type_schema, &array8_schema); + assert_eq!(¶ms[1].type_schema, &array16_schema); + assert_eq!(¶ms[2].type_schema, &array_unlim_schema); Ok(()) } @@ -316,7 +309,8 @@ fn test_borsh_schema_struct() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 2); let pair_def_schema = BorshSchemaContainer { declaration: "Pair".to_string(), definitions: HashMap::from([( @@ -338,8 +332,8 @@ fn test_borsh_schema_struct() -> anyhow::Result<()> { }, )]), }; - assert_eq!(function.params[0].borsh_schema()?, &pair_def_schema); - assert_eq!(function.params[1].borsh_schema()?, &pair_named_def_schema); + assert_eq!(¶ms[0].type_schema, &pair_def_schema); + assert_eq!(¶ms[1].type_schema, &pair_named_def_schema); Ok(()) } @@ -375,7 +369,8 @@ fn test_borsh_schema_enum() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 2); let ip_addr_kind_def_schema = BorshSchemaContainer { declaration: "IpAddrKind".to_string(), definitions: HashMap::from([ @@ -433,8 +428,8 @@ fn test_borsh_schema_enum() -> anyhow::Result<()> { ), ]), }; - assert_eq!(function.params[0].borsh_schema()?, &ip_addr_kind_def_schema); - assert_eq!(function.params[1].borsh_schema()?, &ip_addr_def_schema); + assert_eq!(¶ms[0].type_schema, &ip_addr_kind_def_schema); + assert_eq!(¶ms[1].type_schema, &ip_addr_def_schema); Ok(()) } @@ -470,7 +465,8 @@ fn test_borsh_schema_complex() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 1); + let params = function.params.borsh_schemas()?; + assert_eq!(params.len(), 1); let ip_addr_def_schema = BorshSchemaContainer { declaration: "IpAddr".to_string(), definitions: HashMap::from([ @@ -506,7 +502,7 @@ fn test_borsh_schema_complex() -> anyhow::Result<()> { ), ]), }; - assert_eq!(function.params[0].borsh_schema()?, &ip_addr_def_schema); + assert_eq!(¶ms[0].type_schema, &ip_addr_def_schema); Ok(()) } diff --git a/integration-tests/tests/abi/callbacks.rs b/integration-tests/tests/abi/callbacks.rs index 6751c333..9063f511 100644 --- a/integration-tests/tests/abi/callbacks.rs +++ b/integration-tests/tests/abi/callbacks.rs @@ -1,8 +1,10 @@ use cargo_near_integration_tests::generate_abi_fn; use function_name::named; -use near_abi::{AbiParameter, AbiType}; +use near_abi::{AbiJsonParameter, AbiType}; use schemars::gen::SchemaGenerator; +use crate::util::AsJsonSchema; + #[test] #[named] fn test_callbacks_unwrapped() -> anyhow::Result<()> { @@ -12,7 +14,8 @@ fn test_callbacks_unwrapped() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 0); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 0); assert_eq!(function.callbacks.len(), 2); let bool_schema = SchemaGenerator::default().subschema_for::(); let u32_schema = SchemaGenerator::default().subschema_for::(); @@ -45,7 +48,8 @@ fn test_callbacks_result() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 0); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 0); assert_eq!(function.callbacks.len(), 2); let string_schema = SchemaGenerator::default().subschema_for::(); let u32_schema = SchemaGenerator::default().subschema_for::(); @@ -78,7 +82,8 @@ fn test_callbacks_vec() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 0); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 0); assert_eq!(function.callbacks.len(), 1); let bool_schema = SchemaGenerator::default().subschema_for::(); let u32_schema = SchemaGenerator::default().subschema_for::(); @@ -114,7 +119,8 @@ fn test_callbacks_mixed_with_params() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); assert_eq!(function.callbacks.len(), 2); let bool_schema = SchemaGenerator::default().subschema_for::(); let u32_schema = SchemaGenerator::default().subschema_for::(); @@ -122,21 +128,17 @@ fn test_callbacks_mixed_with_params() -> anyhow::Result<()> { let i32_schema = SchemaGenerator::default().subschema_for::(); let u8_schema = SchemaGenerator::default().subschema_for::(); assert_eq!( - function.params[0], - AbiParameter { + params[0], + AbiJsonParameter { name: "b".to_string(), - typ: AbiType::Json { - type_schema: u32_schema, - } + type_schema: u32_schema, } ); assert_eq!( - function.params[1], - AbiParameter { + params[1], + AbiJsonParameter { name: "d".to_string(), - typ: AbiType::Json { - type_schema: i32_schema, - } + type_schema: i32_schema, } ); assert_eq!( diff --git a/integration-tests/tests/abi/e2e.rs b/integration-tests/tests/abi/e2e.rs index 7ce72e0b..cfb87a13 100644 --- a/integration-tests/tests/abi/e2e.rs +++ b/integration-tests/tests/abi/e2e.rs @@ -1,6 +1,6 @@ use cargo_near_integration_tests::generate_abi_fn; use function_name::named; -use near_abi::{AbiFunction, AbiParameter, AbiType}; +use near_abi::{AbiFunction, AbiJsonParameter, AbiParameters, AbiType}; use schemars::gen::SchemaGenerator; #[test] @@ -24,20 +24,18 @@ fn test_simple_function() -> anyhow::Result<()> { is_init: false, is_payable: false, is_private: false, - params: vec![ - AbiParameter { - name: "a".to_string(), - typ: AbiType::Json { + params: AbiParameters::Json { + args: vec![ + AbiJsonParameter { + name: "a".to_string(), type_schema: u32_schema.clone(), - } - }, - AbiParameter { - name: "b".to_string(), - typ: AbiType::Json { + }, + AbiJsonParameter { + name: "b".to_string(), type_schema: u32_schema.clone(), } - } - ], + ], + }, callbacks: vec![], callbacks_vec: None, result: Some(AbiType::Json { diff --git a/integration-tests/tests/abi/json_schema.rs b/integration-tests/tests/abi/json_schema.rs index b7a10619..a5cb93a1 100644 --- a/integration-tests/tests/abi/json_schema.rs +++ b/integration-tests/tests/abi/json_schema.rs @@ -1,22 +1,8 @@ +use crate::util::AsJsonSchema; use cargo_near_integration_tests::{generate_abi, generate_abi_fn}; use function_name::named; -use near_abi::{AbiParameter, AbiType}; use schemars::schema::Schema; -trait AsJsonSchema { - fn json_schema(&self) -> anyhow::Result<&Schema>; -} - -impl AsJsonSchema for AbiParameter { - fn json_schema(&self) -> anyhow::Result<&Schema> { - if let AbiType::Json { type_schema } = &self.typ { - Ok(type_schema) - } else { - anyhow::bail!("Expected JSON serialization type, but got {:?}", self) - } - } -} - #[test] #[named] fn test_schema_numeric_primitives_signed() -> anyhow::Result<()> { @@ -26,7 +12,8 @@ fn test_schema_numeric_primitives_signed() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 6); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 6); // `format` is an open-ended keyword so one can define their own custom formats. // See https://json-schema.org/draft/2020-12/json-schema-validation.html#name-custom-format-attributes. // We make use of it to annotate `integer` type with specific numeric formats. This has some @@ -80,12 +67,12 @@ fn test_schema_numeric_primitives_signed() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &i8_schema); - assert_eq!(function.params[1].json_schema()?, &i16_schema); - assert_eq!(function.params[2].json_schema()?, &i32_schema); - assert_eq!(function.params[3].json_schema()?, &i64_schema); - assert_eq!(function.params[4].json_schema()?, &i128_schema); - assert_eq!(function.params[5].json_schema()?, &isize_schema); + assert_eq!(¶ms[0].type_schema, &i8_schema); + assert_eq!(¶ms[1].type_schema, &i16_schema); + assert_eq!(¶ms[2].type_schema, &i32_schema); + assert_eq!(¶ms[3].type_schema, &i64_schema); + assert_eq!(¶ms[4].type_schema, &i128_schema); + assert_eq!(¶ms[5].type_schema, &isize_schema); Ok(()) } @@ -99,7 +86,8 @@ fn test_schema_numeric_primitives_unsigned() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 6); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 6); // `format` is an open-ended keyword so one can define their own custom formats. // See https://json-schema.org/draft/2020-12/json-schema-validation.html#name-custom-format-attributes. // We make use of it to annotate `integer` type with specific numeric formats. This has some @@ -159,12 +147,12 @@ fn test_schema_numeric_primitives_unsigned() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &u8_schema); - assert_eq!(function.params[1].json_schema()?, &u16_schema); - assert_eq!(function.params[2].json_schema()?, &u32_schema); - assert_eq!(function.params[3].json_schema()?, &u64_schema); - assert_eq!(function.params[4].json_schema()?, &u128_schema); - assert_eq!(function.params[5].json_schema()?, &usize_schema); + assert_eq!(¶ms[0].type_schema, &u8_schema); + assert_eq!(¶ms[1].type_schema, &u16_schema); + assert_eq!(¶ms[2].type_schema, &u32_schema); + assert_eq!(¶ms[3].type_schema, &u64_schema); + assert_eq!(¶ms[4].type_schema, &u128_schema); + assert_eq!(¶ms[5].type_schema, &usize_schema); Ok(()) } @@ -178,7 +166,8 @@ fn test_schema_numeric_primitives_float() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); // `format` is an open-ended keyword so one can define their own custom formats. // See https://json-schema.org/draft/2020-12/json-schema-validation.html#name-custom-format-attributes. // We make use of it to annotate `integer` type with specific numeric formats. This has some @@ -200,8 +189,8 @@ fn test_schema_numeric_primitives_float() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &f32_schema); - assert_eq!(function.params[1].json_schema()?, &f64_schema); + assert_eq!(¶ms[0].type_schema, &f32_schema); + assert_eq!(¶ms[1].type_schema, &f64_schema); Ok(()) } @@ -215,7 +204,8 @@ fn test_schema_string() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 3); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 3); let string_schema: Schema = serde_json::from_str( r#" { @@ -223,9 +213,9 @@ fn test_schema_string() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &string_schema); - assert_eq!(function.params[1].json_schema()?, &string_schema); - assert_eq!(function.params[2].json_schema()?, &string_schema); + assert_eq!(¶ms[0].type_schema, &string_schema); + assert_eq!(¶ms[1].type_schema, &string_schema); + assert_eq!(¶ms[2].type_schema, &string_schema); Ok(()) } @@ -239,7 +229,8 @@ fn test_schema_other_primitives() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 3); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 3); let char_schema: Schema = serde_json::from_str( r#" { @@ -263,9 +254,9 @@ fn test_schema_other_primitives() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &char_schema); - assert_eq!(function.params[1].json_schema()?, &bool_schema); - assert_eq!(function.params[2].json_schema()?, &unit_schema); + assert_eq!(¶ms[0].type_schema, &char_schema); + assert_eq!(¶ms[1].type_schema, &bool_schema); + assert_eq!(¶ms[2].type_schema, &unit_schema); Ok(()) } @@ -279,7 +270,8 @@ fn test_schema_tuples() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 3); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 3); let tuple1_schema: Schema = serde_json::from_str( r#" { @@ -331,9 +323,9 @@ fn test_schema_tuples() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &tuple1_schema); - assert_eq!(function.params[1].json_schema()?, &tuple2_schema); - assert_eq!(function.params[2].json_schema()?, &tuple3_schema); + assert_eq!(¶ms[0].type_schema, &tuple1_schema); + assert_eq!(¶ms[1].type_schema, &tuple2_schema); + assert_eq!(¶ms[2].type_schema, &tuple3_schema); Ok(()) } @@ -347,7 +339,8 @@ fn test_schema_arrays() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 3); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 3); let array8_schema: Schema = serde_json::from_str( r#" { @@ -382,9 +375,9 @@ fn test_schema_arrays() -> anyhow::Result<()> { } "#, )?; - assert_eq!(function.params[0].json_schema()?, &array8_schema); - assert_eq!(function.params[1].json_schema()?, &array16_schema); - assert_eq!(function.params[2].json_schema()?, &array_unlim_schema); + assert_eq!(¶ms[0].type_schema, &array8_schema); + assert_eq!(¶ms[1].type_schema, &array16_schema); + assert_eq!(¶ms[2].type_schema, &array_unlim_schema); Ok(()) } @@ -419,7 +412,8 @@ fn test_schema_struct() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); let pair_def_schema: Schema = serde_json::from_str( r##" { @@ -434,8 +428,8 @@ fn test_schema_struct() -> anyhow::Result<()> { } "##, )?; - assert_eq!(function.params[0].json_schema()?, &pair_def_schema); - assert_eq!(function.params[1].json_schema()?, &pair_named_def_schema); + assert_eq!(¶ms[0].type_schema, &pair_def_schema); + assert_eq!(¶ms[1].type_schema, &pair_named_def_schema); // Structs with unnamed parameters are serialized as arrays, hence they are represented as // arrays in JSON Schema. @@ -525,7 +519,8 @@ fn test_schema_enum() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); let ip_addr_kind_def_schema: Schema = serde_json::from_str( r##" { @@ -540,8 +535,8 @@ fn test_schema_enum() -> anyhow::Result<()> { } "##, )?; - assert_eq!(function.params[0].json_schema()?, &ip_addr_kind_def_schema); - assert_eq!(function.params[1].json_schema()?, &ip_addr_def_schema); + assert_eq!(¶ms[0].type_schema, &ip_addr_kind_def_schema); + assert_eq!(¶ms[1].type_schema, &ip_addr_def_schema); let ip_addr_kind_schema: Schema = serde_json::from_str( r#" @@ -655,7 +650,8 @@ fn test_schema_complex() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); let ip_addr_kind_def_schema: Schema = serde_json::from_str( r##" { @@ -670,8 +666,8 @@ fn test_schema_complex() -> anyhow::Result<()> { } "##, )?; - assert_eq!(function.params[0].json_schema()?, &ip_addr_kind_def_schema); - assert_eq!(function.params[1].json_schema()?, &ip_addr_def_schema); + assert_eq!(¶ms[0].type_schema, &ip_addr_kind_def_schema); + assert_eq!(¶ms[1].type_schema, &ip_addr_def_schema); let ip_addr_kind_schema: Schema = serde_json::from_str( r#" diff --git a/integration-tests/tests/build/embed.rs b/integration-tests/tests/build/embed.rs index c371eb4f..49f924b1 100644 --- a/integration-tests/tests/build/embed.rs +++ b/integration-tests/tests/build/embed.rs @@ -1,4 +1,4 @@ -use crate::build::util; +use crate::util; use cargo_near_integration_tests::{build_fn, build_fn_with}; use function_name::named; use workspaces::prelude::DevAccountDeployer; @@ -14,7 +14,7 @@ async fn test_build_embed_abi() -> anyhow::Result<()> { } }; - let abi_root = build_result.abi_root.unwrap(); + let mut abi_root = build_result.abi_root.unwrap(); assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; assert_eq!(function.name, "add"); @@ -24,6 +24,8 @@ async fn test_build_embed_abi() -> anyhow::Result<()> { util::fetch_contract_abi(&build_result.wasm) ); add?; + // WASM hash is not included in the embedded ABI + abi_root.metadata.wasm_hash = None; assert_eq!(abi_root, actual_abi?); Ok(()) diff --git a/integration-tests/tests/build/mod.rs b/integration-tests/tests/build/mod.rs index a982d8a8..2451e4c8 100644 --- a/integration-tests/tests/build/mod.rs +++ b/integration-tests/tests/build/mod.rs @@ -1,9 +1,9 @@ +use crate::util; use cargo_near_integration_tests::build_fn; use function_name::named; mod embed; mod opts; -mod util; #[tokio::test] #[named] diff --git a/integration-tests/tests/build/opts.rs b/integration-tests/tests/build/opts.rs index 9c9ada54..24db5c48 100644 --- a/integration-tests/tests/build/opts.rs +++ b/integration-tests/tests/build/opts.rs @@ -95,11 +95,13 @@ async fn test_build_opt_doc_embed() -> anyhow::Result<()> { } }; - let abi_root = build_result.abi_root.unwrap(); + let mut abi_root = build_result.abi_root.unwrap(); assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; assert_eq!(function.doc.as_ref().unwrap(), " Adds `a` and `b`."); + // WASM hash is not included in the embedded ABI + abi_root.metadata.wasm_hash = None; assert_eq!( util::fetch_contract_abi(&build_result.wasm).await?, abi_root diff --git a/integration-tests/tests/cargo/mod.rs b/integration-tests/tests/cargo/mod.rs index 37a1701a..cd1fb8fe 100644 --- a/integration-tests/tests/cargo/mod.rs +++ b/integration-tests/tests/cargo/mod.rs @@ -5,6 +5,8 @@ use git2::Repository; use std::collections::HashMap; use tempfile::TempDir; +use crate::util::AsJsonSchema; + fn clone_git_repo(version: &str) -> anyhow::Result { let temp_dir = tempfile::tempdir()?; let repo_dir = temp_dir.path(); @@ -18,7 +20,7 @@ fn clone_git_repo(version: &str) -> anyhow::Result { #[test] #[named] fn test_dependency_local_path() -> anyhow::Result<()> { - let near_sdk_dir = clone_git_repo("792d5eb26d26a0878dbf59e304afa4e19540c317")?; + let near_sdk_dir = clone_git_repo("6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b")?; let near_sdk_dep_path = near_sdk_dir.path().join("near-sdk"); // near-sdk = { path = "::path::", features = ["abi"] } @@ -31,7 +33,8 @@ fn test_dependency_local_path() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -39,7 +42,7 @@ fn test_dependency_local_path() -> anyhow::Result<()> { #[test] #[named] fn test_dependency_local_path_with_version() -> anyhow::Result<()> { - let near_sdk_dir = clone_git_repo("792d5eb26d26a0878dbf59e304afa4e19540c317")?; + let near_sdk_dir = clone_git_repo("6d73c9ff4fd095fc23eaa000c14ab65c15c4aa6b")?; let near_sdk_dep_path = near_sdk_dir.path().join("near-sdk"); // near-sdk = { path = "::path::", version = "4.1.0-pre.3", features = ["abi"] } @@ -52,7 +55,8 @@ fn test_dependency_local_path_with_version() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -71,7 +75,8 @@ fn test_dependency_explicit() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -88,7 +93,8 @@ fn test_dependency_no_default_features() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -105,7 +111,8 @@ fn test_dependency_multiple_features() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -126,7 +133,8 @@ fn test_dependency_platform_specific() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -155,7 +163,8 @@ fn test_dependency_renamed() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } @@ -178,7 +187,8 @@ fn test_dependency_patch() -> anyhow::Result<()> { assert_eq!(abi_root.body.functions.len(), 1); let function = &abi_root.body.functions[0]; - assert_eq!(function.params.len(), 2); + let params = function.params.json_schemas()?; + assert_eq!(params.len(), 2); Ok(()) } diff --git a/integration-tests/tests/lib.rs b/integration-tests/tests/lib.rs index efbccdf1..9a988669 100644 --- a/integration-tests/tests/lib.rs +++ b/integration-tests/tests/lib.rs @@ -1,3 +1,4 @@ mod abi; mod build; mod cargo; +mod util; diff --git a/integration-tests/tests/build/util.rs b/integration-tests/tests/util.rs similarity index 51% rename from integration-tests/tests/build/util.rs rename to integration-tests/tests/util.rs index dcdffec1..0cdfcb22 100644 --- a/integration-tests/tests/build/util.rs +++ b/integration-tests/tests/util.rs @@ -1,4 +1,5 @@ use near_abi::AbiRoot; +use near_abi::{AbiBorshParameter, AbiJsonParameter, AbiParameters}; use serde_json::json; use workspaces::prelude::DevAccountDeployer; @@ -25,3 +26,31 @@ pub async fn fetch_contract_abi(wasm: &[u8]) -> anyhow::Result { let outcome_json = zstd::decode_all(outcome.result.as_slice())?; Ok(serde_json::from_slice::(&outcome_json)?) } + +pub trait AsBorshSchema { + fn borsh_schemas(&self) -> anyhow::Result<&Vec>; +} + +impl AsBorshSchema for AbiParameters { + fn borsh_schemas(&self) -> anyhow::Result<&Vec> { + if let AbiParameters::Borsh { args } = &self { + Ok(args) + } else { + anyhow::bail!("Expected Borsh serialization type, but got {:?}", self) + } + } +} + +pub trait AsJsonSchema { + fn json_schemas(&self) -> anyhow::Result<&Vec>; +} + +impl AsJsonSchema for AbiParameters { + fn json_schemas(&self) -> anyhow::Result<&Vec> { + if let AbiParameters::Json { args } = &self { + Ok(args) + } else { + anyhow::bail!("Expected JSON serialization type, but got {:?}", self) + } + } +}