Skip to content

Commit

Permalink
feat: add proper support for borsh schema containers in ABI (#872)
Browse files Browse the repository at this point in the history
* add proper support for borsh schema containers

* rebuild examples

* improve borsh serde impls

* add tests
  • Loading branch information
itegulov committed Aug 1, 2022
1 parent 6730ae8 commit d784831
Show file tree
Hide file tree
Showing 8 changed files with 556 additions and 86 deletions.
81 changes: 64 additions & 17 deletions examples/abi/res/abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,57 +15,104 @@
"params": [
{
"name": "a",
"serialization_type": "json",
"type_schema": {
"$ref": "#/definitions/Pair"
},
"serialization_type": "json"
}
},
{
"name": "b",
"serialization_type": "json",
"type_schema": {
"$ref": "#/definitions/Pair"
},
"serialization_type": "json"
}
}
],
"result": {
"serialization_type": "json",
"type_schema": {
"$ref": "#/definitions/Pair"
}
}
},
{
"name": "add_borsh",
"is_view": true,
"params": [
{
"name": "a",
"serialization_type": "borsh",
"type_schema": {
"declaration": "Pair",
"definitions": {
"Pair": {
"Struct": [
"u32",
"u32"
]
}
}
}
},
"serialization_type": "json"
{
"name": "b",
"serialization_type": "borsh",
"type_schema": {
"declaration": "Pair",
"definitions": {
"Pair": {
"Struct": [
"u32",
"u32"
]
}
}
}
}
],
"result": {
"serialization_type": "borsh",
"type_schema": {
"declaration": "Pair",
"definitions": {
"Pair": {
"Struct": [
"u32",
"u32"
]
}
}
}
}
},
{
"name": "add_callback",
"is_view": true,
"callbacks": [
{
"serialization_type": "json",
"type_schema": {
"$ref": "#/definitions/DoublePair"
},
"serialization_type": "json"
}
},
{
"serialization_type": "json",
"type_schema": {
"$ref": "#/definitions/DoublePair"
},
"serialization_type": "json"
}
}
],
"callbacks_vec": {
"serialization_type": "json",
"type_schema": {
"type": "array",
"items": {
"$ref": "#/definitions/DoublePair"
}
},
"serialization_type": "json"
"$ref": "#/definitions/DoublePair"
}
},
"result": {
"serialization_type": "json",
"type_schema": {
"$ref": "#/definitions/DoublePair"
},
"serialization_type": "json"
}
}
}
],
Expand Down
Binary file modified examples/abi/res/abi.wasm
Binary file not shown.
9 changes: 7 additions & 2 deletions examples/abi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use near_sdk::__private::schemars::JsonSchema;
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::borsh::{self, BorshDeserialize, BorshSchema, BorshSerialize};
use near_sdk::near_bindgen;
use near_sdk::serde::{Deserialize, Serialize};

#[derive(JsonSchema, Serialize, Deserialize)]
#[derive(JsonSchema, Serialize, Deserialize, BorshDeserialize, BorshSerialize, BorshSchema)]
pub struct Pair(u32, u32);

#[derive(JsonSchema, Serialize, Deserialize)]
Expand All @@ -22,6 +22,11 @@ impl Adder {
sum_pair(&a, &b)
}

#[result_serializer(borsh)]
pub fn add_borsh(&self, #[serializer(borsh)] a: Pair, #[serializer(borsh)] b: Pair) -> Pair {
sum_pair(&a, &b)
}

pub fn add_callback(
&self,
#[callback_unwrap] a: DoublePair,
Expand Down
Binary file modified examples/fungible-token/res/fungible_token.wasm
Binary file not shown.
Binary file modified examples/non-fungible-token/res/non_fungible_token.wasm
Binary file not shown.
69 changes: 22 additions & 47 deletions near-sdk-macros/src/core_impl/abi/abi_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{ImplItemMethodInfo, MethodType};
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use syn::spanned::Spanned;
use syn::ReturnType;
use syn::{ReturnType, Type};

impl ImplItemMethodInfo {
/// Generates ABI struct for this function.
Expand Down Expand Up @@ -54,25 +54,19 @@ impl ImplItemMethodInfo {
let mut callback_vec: Option<TokenStream2> = None;
for arg in &self.attr_signature_info.args {
let typ = &arg.ty;
let serialization_type = abi_serialization_type(&arg.serializer_ty);
let arg_name = arg.ident.to_string();
match arg.bindgen_ty {
BindgenArgType::Regular => {
let abi_type = generate_abi_type(typ, &arg.serializer_ty);
params.push(quote! {
near_sdk::__private::AbiParameter {
name: #arg_name.to_string(),
type_schema: gen.subschema_for::<#typ>(),
serialization_type: #serialization_type,
typ: #abi_type
}
});
}
BindgenArgType::CallbackArg => {
callbacks.push(quote! {
near_sdk::__private::AbiType {
type_schema: gen.subschema_for::<#typ>(),
serialization_type: #serialization_type,
}
});
callbacks.push(generate_abi_type(typ, &arg.serializer_ty));
}
BindgenArgType::CallbackResultArg => {
let typ = if let Some(ok_type) = utils::extract_ok_type(typ) {
Expand All @@ -85,12 +79,7 @@ impl ImplItemMethodInfo {
)
.into_compile_error();
};
callbacks.push(quote! {
near_sdk::__private::AbiType {
type_schema: gen.subschema_for::<#typ>(),
serialization_type: #serialization_type,
}
});
callbacks.push(generate_abi_type(typ, &arg.serializer_ty));
}
BindgenArgType::CallbackArgVec => {
if callback_vec.is_none() {
Expand All @@ -103,14 +92,10 @@ impl ImplItemMethodInfo {
)
.into_compile_error();
};
callback_vec = Some(quote! {
Some(
near_sdk::__private::AbiType {
type_schema: gen.subschema_for::<#typ>(),
serialization_type: #serialization_type,
}
)
})

let abi_type =
generate_abi_type(typ, &self.attr_signature_info.result_serializer);
callback_vec = Some(quote! { Some(#abi_type) })
} else {
return syn::Error::new(
Span::call_site(),
Expand Down Expand Up @@ -146,16 +131,9 @@ impl ImplItemMethodInfo {
)
.into_compile_error();
};
let serialization_type =
abi_serialization_type(&self.attr_signature_info.result_serializer);
quote! {
Some(
near_sdk::__private::AbiType {
type_schema: gen.subschema_for::<#ty>(),
serialization_type: #serialization_type,
}
)
}
let abi_type =
generate_abi_type(ty, &self.attr_signature_info.result_serializer);
quote! { Some(#abi_type) }
}
ReturnType::Type(_, ty) if is_handles_result => {
return syn::Error::new(
Expand All @@ -165,16 +143,9 @@ impl ImplItemMethodInfo {
.to_compile_error();
}
ReturnType::Type(_, ty) => {
let serialization_type =
abi_serialization_type(&self.attr_signature_info.result_serializer);
quote! {
Some(
near_sdk::__private::AbiType {
type_schema: gen.subschema_for::<#ty>(),
serialization_type: #serialization_type,
}
)
}
let abi_type =
generate_abi_type(ty, &self.attr_signature_info.result_serializer);
quote! { Some(#abi_type) }
}
},
};
Expand All @@ -195,13 +166,17 @@ impl ImplItemMethodInfo {
}
}

fn abi_serialization_type(serializer_type: &SerializerType) -> TokenStream2 {
fn generate_abi_type(ty: &Type, serializer_type: &SerializerType) -> TokenStream2 {
match serializer_type {
SerializerType::JSON => quote! {
near_sdk::__private::AbiSerializationType::Json
near_sdk::__private::AbiType::Json {
type_schema: gen.subschema_for::<#ty>(),
}
},
SerializerType::Borsh => quote! {
near_sdk::__private::AbiSerializationType::Borsh
near_sdk::__private::AbiType::Borsh {
type_schema: #ty::schema_container(),
}
},
}
}
Loading

0 comments on commit d784831

Please sign in to comment.