diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1785675c4..ea0e1db5b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,8 +26,8 @@ jobs: - uses: Swatinem/rust-cache@v1 - name: Downgrade dependencies run: | - cargo update -p clap@4.5.1 --precise 4.4.18 - cd examples/adder && cargo update -p clap@4.5.1 --precise 4.4.18 + cargo update -p clap@4.5.4 --precise 4.4.18 + cd examples/adder && cargo update -p clap@4.5.4 --precise 4.4.18 - name: test run: cargo test --all --features unstable,legacy lint: @@ -46,6 +46,20 @@ jobs: - name: Test Format run: cargo fmt -- --check - run: cargo clippy --tests --all-features -- -Dclippy::all + compilation: + name: Compilation tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + default: true + - uses: Swatinem/rust-cache@v1 + - name: Compilation tests + run: cargo test --package near-sdk --test compilation_tests --features abi --features unstable -- compilation_tests --exact --nocapture windows: name: Windows runs-on: windows-latest diff --git a/.github/workflows/typo.yml b/.github/workflows/typo.yml new file mode 100644 index 000000000..021c55fd4 --- /dev/null +++ b/.github/workflows/typo.yml @@ -0,0 +1,13 @@ +name: Typo Checker +on: [pull_request] + +jobs: + run: + name: Spell Check with Typos + runs-on: ubuntu-latest + steps: + - name: Checkout Actions Repository + uses: actions/checkout@v2 + - name: Check spelling of the entire repository + uses: crate-ci/typos@v1.11.1 + diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 000000000..d2722d35d --- /dev/null +++ b/.typos.toml @@ -0,0 +1 @@ +[default.extend-words] diff --git a/CHANGELOG.md b/CHANGELOG.md index 794fcbe71..c878d0f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ## [Unreleased] +## [5.1.0](https://github.com/near/near-sdk-rs/compare/near-sdk-v5.0.0...near-sdk-v5.1.0) - 2024-03-28 + +### Added +- Finalize `#[near]` attribute-macro implementation with the support for custom parameters passing to serializer attributes `#[near(serializers = [borsh(...)])]` ([#1158](https://github.com/near/near-sdk-rs/pull/1158)) +- Introduce `#[near]` macro to further streamline contracts development reducing the boilerplate! ([#1142](https://github.com/near/near-sdk-rs/pull/1142)) + +### Other +- add typo checker in ci ([#1159](https://github.com/near/near-sdk-rs/pull/1159)) + ## [5.0.0](https://github.com/near/near-sdk-rs/compare/4.1.1...near-sdk-v5.0.0) - 2024-02-21 ### Highlights @@ -326,7 +335,7 @@ Get your fully configured development environment in under 1 minute using [GitHu * Move type aliases and core types to near-sdk to avoid coupling. [PR 415](https://github.com/near/near-sdk-rs/pull/415). * Implements new `Lazy` type under the new `unstable` feature which is a lazily loaded storage value. [PR 409](https://github.com/near/near-sdk-rs/pull/409). * fix(promise): `PromiseOrValue` now correctly sets `should_return` flag correctly on serialization. [PR 407](https://github.com/near/near-sdk-rs/pull/407). -* fix(tree_map): Correctly panic when range indices are exluded and `start > end`. [PR 392](https://github.com/near/near-sdk-rs/pull/392). +* fix(tree_map): Correctly panic when range indices are excluded and `start > end`. [PR 392](https://github.com/near/near-sdk-rs/pull/392). * Implement `FromStr` for json types to allow calling `.parse()` to convert them. * `ValidAccountId` [PR 391](https://github.com/near/near-sdk-rs/pull/391). * `Base58CryptoHash` [PR 398](https://github.com/near/near-sdk-rs/pull/398). @@ -338,7 +347,7 @@ Get your fully configured development environment in under 1 minute using [GitHu * Update syscall interface to no longer go through `BLOCKCHAIN_INTERFACE`. Instead uses `near_sdk::sys` which is under the `unstable` feature flag if needed. [PR 417](https://github.com/near/near-sdk-rs/pull/417). * Set up global allocator by default for WASM architectures. [PR 429](https://github.com/near/near-sdk-rs/pull/429). * This removes the re-export of `wee_alloc` because if this feature is enabled, the allocator will already be set. - * Deprecates `setup_alloc!` macro as this will be setup by default, as long as the `wee_alloc` feature is not specifically disabled. In this case, the allocator can be overriden to a custom one or set manually if intended. + * Deprecates `setup_alloc!` macro as this will be setup by default, as long as the `wee_alloc` feature is not specifically disabled. In this case, the allocator can be overridden to a custom one or set manually if intended. * Update `TreeMap` iterator implementation to avoid unnecessary storage reads. [PR 428](https://github.com/near/near-sdk-rs/pull/428). * Update `AccountId` to be a newtype with merged functionality from `ValidAccountId`. [PR 448](https://github.com/near/near-sdk-rs/pull/448) * Removes `ValidAccountId` to avoid having multiple types for account IDs. diff --git a/Cargo.toml b/Cargo.toml index b605a7872..0ac56340c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ exclude = ["examples/"] [workspace.package] -version = "5.0.0" +version = "5.1.0" # Special triple # comment for ci. [patch.crates-io] diff --git a/README.md b/README.md index 8f2be4bca..e0c0019bd 100644 --- a/README.md +++ b/README.md @@ -40,18 +40,17 @@ ## Example -Wrap a struct in `#[near_bindgen]` and it generates a smart contract compatible with the NEAR blockchain: +Wrap a struct in `#[near]` and it generates a smart contract compatible with the NEAR blockchain: ```rust -use near_sdk::{near_bindgen, env}; +use near_sdk::{near, env}; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] +#[derive(Default)] pub struct StatusMessage { records: HashMap, } -#[near_bindgen] +#[near] impl StatusMessage { pub fn set_status(&mut self, message: String) { let account_id = env::signer_account_id(); @@ -97,7 +96,7 @@ to see various usages of cross contract calls, including **system-level actions* We can define an initialization method that can be used to initialize the state of the contract. `#[init]` verifies that the contract has not been initialized yet (the contract state doesn't exist) and will panic otherwise. ```rust -#[near_bindgen] +#[near] impl StatusMessage { #[init] pub fn new(user: String, status: String) -> Self { @@ -119,16 +118,15 @@ impl Default for StatusMessage { ``` You can also prohibit `Default` trait initialization by using `near_sdk::PanicOnDefault` helper macro. E.g.: ```rust -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] +#[derive(PanicOnDefault)] pub struct StatusMessage { records: HashMap, } ``` ### Payable methods -We can allow methods to accept token transfer together with the function call. This is done so that contracts can define a fee in tokens that needs to be payed when they are used. By the default the methods are not payable and they will panic if someone will attempt to transfer tokens to them during the invocation. This is done for safety reason, in case someone accidentally transfers tokens during the function call. +We can allow methods to accept token transfer together with the function call. This is done so that contracts can define a fee in tokens that needs to be paid when they are used. By the default the methods are not payable and they will panic if someone will attempt to transfer tokens to them during the invocation. This is done for safety reason, in case someone accidentally transfers tokens during the function call. To declare a payable method simply use `#[payable]` decorator: ```rust @@ -183,15 +181,13 @@ The general workflow is the following: 2. Crate needs to have one `pub` struct that will represent the smart contract itself: * The struct needs to implement `Default` trait which NEAR will use to create the initial state of the contract upon its first usage; - * The struct also needs to implement `BorshSerialize` and `BorshDeserialize` traits which NEAR will use to save/load contract's internal state; Here is an example of a smart contract struct: ```rust - use near_sdk::{near_bindgen, env}; + use near_sdk::{near, env}; - #[near_bindgen] - #[derive(Default, BorshSerialize, BorshDeserialize)] - #[borsh(crate = "near_sdk::borsh")] + #[near(contract_state)] + #[derive(Default)] pub struct MyContract { data: HashMap } @@ -200,12 +196,12 @@ The general workflow is the following: 3. Define methods that NEAR will expose as smart contract methods: * You are free to define any methods for the struct but only public methods will be exposed as smart contract methods; * Methods need to use either `&self`, `&mut self`, or `self`; - * Decorate the `impl` section with `#[near_bindgen]` macro. That is where all the M.A.G.I.C. (Macros-Auto-Generated Injected Code) happens; + * Decorate the `impl` section with `#[near]` macro. That is where all the M.A.G.I.C. (Macros-Auto-Generated Injected Code) happens; * If you need to use blockchain interface, e.g. to get the current account id then you can access it with `env::*`; Here is an example of smart contract methods: ```rust - #[near_bindgen] + #[near] impl MyContract { pub fn insert_data(&mut self, key: u64, value: u64) -> Option { self.data.insert(key) diff --git a/examples/adder/src/lib.rs b/examples/adder/src/lib.rs index 7cb39dd6f..fc6095fb2 100644 --- a/examples/adder/src/lib.rs +++ b/examples/adder/src/lib.rs @@ -1,27 +1,19 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{near_bindgen, NearSchema}; +use near_sdk::near; -#[derive(NearSchema, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] -#[serde(crate = "near_sdk::serde")] -#[abi(json, borsh)] +#[near(serializers=[borsh, json])] pub struct Pair(u32, u32); -#[derive(NearSchema, Serialize, Deserialize)] -#[serde(crate = "near_sdk::serde")] -#[abi(json, borsh)] +#[near(serializers=[borsh, json])] pub struct DoublePair { first: Pair, second: Pair, } -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Default)] +#[near(serializers=[borsh, json], contract_state)] pub struct Adder {} -#[near_bindgen] +#[near] impl Adder { /// Adds two pairs point-wise. pub fn add(&self, a: Pair, b: Pair) -> Pair { diff --git a/examples/callback-results/src/lib.rs b/examples/callback-results/src/lib.rs index f94302b34..1faa13e46 100644 --- a/examples/callback-results/src/lib.rs +++ b/examples/callback-results/src/lib.rs @@ -1,12 +1,12 @@ use near_sdk::require; -use near_sdk::{env, near_bindgen, Promise, PromiseError}; +use near_sdk::{env, near, Promise, PromiseError}; const A_VALUE: u8 = 8; -#[near_bindgen] +#[near(contract_state)] pub struct Callback; -#[near_bindgen] +#[near] impl Callback { /// Call functions a, b, and c asynchronously and handle results with `handle_callbacks`. pub fn call_all(fail_b: bool, c_value: u8, d_value: u8) -> Promise { diff --git a/examples/cross-contract-calls/high-level/src/lib.rs b/examples/cross-contract-calls/high-level/src/lib.rs index b14eb1401..3f20bf058 100644 --- a/examples/cross-contract-calls/high-level/src/lib.rs +++ b/examples/cross-contract-calls/high-level/src/lib.rs @@ -1,13 +1,11 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::env; -use near_sdk::{log, near_bindgen, PromiseOrValue}; +use near_sdk::{log, near, PromiseOrValue}; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Default)] +#[near(contract_state)] pub struct CrossContract {} -#[near_bindgen] +#[near] impl CrossContract { pub fn factorial(&self, n: u32) -> PromiseOrValue { if n <= 1 { diff --git a/examples/cross-contract-calls/low-level/src/lib.rs b/examples/cross-contract-calls/low-level/src/lib.rs index 58129a150..0a5e1533b 100644 --- a/examples/cross-contract-calls/low-level/src/lib.rs +++ b/examples/cross-contract-calls/low-level/src/lib.rs @@ -1,6 +1,5 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::serde_json; -use near_sdk::{env, near_bindgen, require, Gas, NearToken, PromiseResult}; +use near_sdk::{env, near, require, Gas, NearToken, PromiseResult}; // Prepaid gas for a single (not inclusive of recursion) `factorial` call. const FACTORIAL_CALL_GAS: Gas = Gas::from_tgas(20); @@ -8,12 +7,11 @@ const FACTORIAL_CALL_GAS: Gas = Gas::from_tgas(20); // Prepaid gas for a single `factorial_mult` call. const FACTORIAL_MULT_CALL_GAS: Gas = Gas::from_tgas(10); -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Default)] +#[near(contract_state)] pub struct CrossContract {} -#[near_bindgen] +#[near] impl CrossContract { pub fn factorial(&self, n: u32) { if n <= 1 { diff --git a/examples/factory-contract/high-level/src/lib.rs b/examples/factory-contract/high-level/src/lib.rs index bbfed725b..7b1167ff6 100644 --- a/examples/factory-contract/high-level/src/lib.rs +++ b/examples/factory-contract/high-level/src/lib.rs @@ -1,10 +1,8 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::PromiseError; -use near_sdk::{env, ext_contract, near_bindgen, AccountId, NearToken, Promise}; +use near_sdk::{env, ext_contract, near, AccountId, NearToken, Promise}; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Default)] +#[near(contract_state)] pub struct FactoryContract {} // If the `ext_contract` name is not provided explicitly, the namespace for generated methods is @@ -15,7 +13,7 @@ pub trait ExtStatusMessage { fn get_status(&self, account_id: AccountId) -> Option; } -#[near_bindgen] +#[near] impl FactoryContract { pub fn deploy_status_message(&self, account_id: AccountId, amount: NearToken) { Promise::new(account_id) diff --git a/examples/factory-contract/low-level/src/lib.rs b/examples/factory-contract/low-level/src/lib.rs index 403f629a4..d2bda474e 100644 --- a/examples/factory-contract/low-level/src/lib.rs +++ b/examples/factory-contract/low-level/src/lib.rs @@ -1,17 +1,15 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::json_types::U128; use near_sdk::serde_json; -use near_sdk::{env, near_bindgen, AccountId, Gas, NearToken, PromiseResult}; +use near_sdk::{env, near, AccountId, Gas, NearToken, PromiseResult}; // Prepaid gas for making a single simple call. const SINGLE_CALL_GAS: Gas = Gas::from_tgas(20); -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Default)] +#[near(contract_state)] pub struct FactoryContract {} -#[near_bindgen] +#[near] impl FactoryContract { pub fn deploy_status_message(&self, account_id: AccountId, amount: U128) { let promise_idx = env::promise_batch_create(&account_id); diff --git a/examples/fungible-token/ft/src/lib.rs b/examples/fungible-token/ft/src/lib.rs index baf7dc3f9..a6be56935 100644 --- a/examples/fungible-token/ft/src/lib.rs +++ b/examples/fungible-token/ft/src/lib.rs @@ -24,17 +24,15 @@ use near_contract_standards::fungible_token::{ use near_contract_standards::storage_management::{ StorageBalance, StorageBalanceBounds, StorageManagement, }; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::borsh::BorshSerialize; use near_sdk::collections::LazyOption; use near_sdk::json_types::U128; use near_sdk::{ - env, log, near_bindgen, require, AccountId, BorshStorageKey, NearToken, PanicOnDefault, - PromiseOrValue, + env, log, near, require, AccountId, BorshStorageKey, NearToken, PanicOnDefault, PromiseOrValue, }; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(PanicOnDefault)] +#[near(contract_state)] pub struct Contract { token: FungibleToken, metadata: LazyOption, @@ -49,7 +47,7 @@ enum StorageKey { Metadata, } -#[near_bindgen] +#[near] impl Contract { /// Initializes the contract with the given total supply owned by the given `owner_id` with /// default metadata (for example purposes only). @@ -94,7 +92,7 @@ impl Contract { } } -#[near_bindgen] +#[near] impl FungibleTokenCore for Contract { #[payable] fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { @@ -121,7 +119,7 @@ impl FungibleTokenCore for Contract { } } -#[near_bindgen] +#[near] impl FungibleTokenResolver for Contract { #[private] fn ft_resolve_transfer( @@ -139,7 +137,7 @@ impl FungibleTokenResolver for Contract { } } -#[near_bindgen] +#[near] impl StorageManagement for Contract { #[payable] fn storage_deposit( @@ -175,7 +173,7 @@ impl StorageManagement for Contract { } } -#[near_bindgen] +#[near] impl FungibleTokenMetadataProvider for Contract { fn ft_metadata(&self) -> FungibleTokenMetadata { self.metadata.get().unwrap() diff --git a/examples/fungible-token/test-contract-defi/src/lib.rs b/examples/fungible-token/test-contract-defi/src/lib.rs index e7fdd71f1..8b6b7542c 100644 --- a/examples/fungible-token/test-contract-defi/src/lib.rs +++ b/examples/fungible-token/test-contract-defi/src/lib.rs @@ -2,17 +2,15 @@ Some hypothetical DeFi contract that will do smart things with the transferred tokens */ use near_contract_standards::fungible_token::{receiver::FungibleTokenReceiver, Balance}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::json_types::U128; -use near_sdk::{env, log, near_bindgen, require, AccountId, Gas, PanicOnDefault, PromiseOrValue}; +use near_sdk::{env, log, near, require, AccountId, Gas, PanicOnDefault, PromiseOrValue}; const BASE_GAS: u64 = 5_000_000_000_000; const PROMISE_CALL: u64 = 5_000_000_000_000; const GAS_FOR_FT_ON_TRANSFER: Gas = Gas::from_gas(BASE_GAS + PROMISE_CALL); -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(PanicOnDefault)] +#[near(contract_state)] pub struct DeFi { fungible_token_account_id: AccountId, } @@ -22,7 +20,7 @@ trait ValueReturnTrait { fn value_please(&self, amount_to_return: String) -> PromiseOrValue; } -#[near_bindgen] +#[near] impl DeFi { #[init] pub fn new(fungible_token_account_id: AccountId) -> Self { @@ -31,7 +29,7 @@ impl DeFi { } } -#[near_bindgen] +#[near] impl FungibleTokenReceiver for DeFi { /// If given `msg: "take-my-money", immediately returns U128::From(0) /// Otherwise, makes a cross-contract call to own `value_please` function, passing `msg` @@ -62,7 +60,7 @@ impl FungibleTokenReceiver for DeFi { } } -#[near_bindgen] +#[near] impl ValueReturnTrait for DeFi { fn value_please(&self, amount_to_return: String) -> PromiseOrValue { log!("in value_please, amount_to_return = {}", amount_to_return); diff --git a/examples/fungible-token/tests/workspaces.rs b/examples/fungible-token/tests/workspaces.rs index 9579b07e4..88ef49a08 100644 --- a/examples/fungible-token/tests/workspaces.rs +++ b/examples/fungible-token/tests/workspaces.rs @@ -180,7 +180,7 @@ async fn test_storage_deposit_refunds_excessive_deposit() -> anyhow::Result<()> assert_eq!(storage_balance_bounds.min, minimal_deposit.as_yoctonear().into()); assert_eq!(storage_balance_bounds.max, minimal_deposit.as_yoctonear().into()); - // Check that a non-registerred account does not have storage balance + // Check that a non-registered account does not have storage balance // #[derive(near_sdk::serde::Serialize, near_sdk::serde::Deserialize)] #[serde(crate = "near_sdk::serde")] @@ -190,7 +190,7 @@ async fn test_storage_deposit_refunds_excessive_deposit() -> anyhow::Result<()> } let storage_balance_bounds: Option = contract .call("storage_balance_of") - .args_json(near_sdk::serde_json::json!({"account_id": "non-registerred-account"})) + .args_json(near_sdk::serde_json::json!({"account_id": "non-registered-account"})) .view() .await? .json()?; diff --git a/examples/lockable-fungible-token/src/lib.rs b/examples/lockable-fungible-token/src/lib.rs index 150677431..824858dcf 100644 --- a/examples/lockable-fungible-token/src/lib.rs +++ b/examples/lockable-fungible-token/src/lib.rs @@ -1,12 +1,11 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::collections::UnorderedMap; -use near_sdk::{env, json_types::U128, near_bindgen, AccountId, PanicOnDefault}; +use near_sdk::{env, json_types::U128, near, AccountId, PanicOnDefault}; use std::collections::HashMap; type Balance = u128; -#[derive(Default, BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Default)] +#[near] pub struct Account { /// Current unlocked balance pub balance: Balance, @@ -46,9 +45,8 @@ impl Account { } } -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(PanicOnDefault)] +#[near(contract_state)] pub struct FunToken { /// AccountID -> Account details. pub accounts: UnorderedMap, @@ -57,7 +55,7 @@ pub struct FunToken { pub total_supply: Balance, } -#[near_bindgen] +#[near] impl FunToken { #[init] #[handle_result] diff --git a/examples/mission-control/src/account.rs b/examples/mission-control/src/account.rs index 720dae057..15da4a915 100644 --- a/examples/mission-control/src/account.rs +++ b/examples/mission-control/src/account.rs @@ -1,12 +1,9 @@ +use crate::asset::*; +use crate::rate::*; use std::collections::HashMap; use std::ops; -use near_sdk::NearSchema; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; - -use crate::asset::*; -use crate::rate::*; +use near_sdk::near; #[derive( PartialEq, @@ -15,20 +12,16 @@ use crate::rate::*; Hash, Clone, Copy, - Serialize, - Deserialize, Debug, - BorshDeserialize, - BorshSerialize, - NearSchema, )] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers = [json, borsh])] pub struct Quantity(pub i32); -#[derive(Clone, Serialize, Deserialize, BorshDeserialize, BorshSerialize, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near] +pub struct X; + +#[derive(Clone)] +#[near(serializers = [json, borsh])] pub struct Account(pub HashMap); pub enum Tranx { diff --git a/examples/mission-control/src/agent.rs b/examples/mission-control/src/agent.rs index 86cb55bf3..81de55de4 100644 --- a/examples/mission-control/src/agent.rs +++ b/examples/mission-control/src/agent.rs @@ -1,13 +1,11 @@ use crate::account::*; use crate::asset::*; use crate::rate::*; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; use std::collections::HashMap; +use near_sdk::near; -#[derive(Clone, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Clone)] +#[near(serializers=[json, borsh])] pub struct Agent { pub account: Account, pub is_alive: bool, diff --git a/examples/mission-control/src/asset.rs b/examples/mission-control/src/asset.rs index 2eddc3aeb..87a65fcdf 100644 --- a/examples/mission-control/src/asset.rs +++ b/examples/mission-control/src/asset.rs @@ -1,6 +1,4 @@ -use near_sdk::NearSchema; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; +use near_sdk::near; #[derive( PartialEq, @@ -10,14 +8,8 @@ use near_sdk::serde::{Deserialize, Serialize}; Hash, Clone, Copy, - Serialize, - Deserialize, - BorshDeserialize, - BorshSerialize, - NearSchema, )] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers = [json, borsh])] pub enum Resource { Battery, RgbSensor, @@ -33,14 +25,8 @@ pub enum Resource { Hash, Clone, Copy, - Serialize, - Deserialize, - BorshDeserialize, - BorshSerialize, - NearSchema, )] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers = [json, borsh])] pub enum Reward { Score, Token, @@ -57,14 +43,8 @@ pub enum Reward { Hash, Clone, Copy, - Serialize, - Deserialize, - BorshDeserialize, - BorshSerialize, - NearSchema, )] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers = [json, borsh])] pub enum Asset { Resource(Resource), Reward(Reward), @@ -76,16 +56,10 @@ pub enum Asset { PartialEq, Eq, Hash, - Serialize, - Deserialize, PartialOrd, Ord, - BorshDeserialize, - BorshSerialize, - NearSchema )] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers = [json, borsh])] pub enum Exchange { MissionTimeWithResource, MissionTimeWithTrust, diff --git a/examples/mission-control/src/mission_control.rs b/examples/mission-control/src/mission_control.rs index daf5ffeec..74f141a42 100644 --- a/examples/mission-control/src/mission_control.rs +++ b/examples/mission-control/src/mission_control.rs @@ -3,22 +3,19 @@ use crate::agent::Agent; use crate::asset::*; use crate::rate::*; use near_sdk::AccountId; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{env, near_bindgen}; +use near_sdk::env; use std::collections::HashMap; +use near_sdk::near; -#[near_bindgen] -#[derive(Serialize, Deserialize, BorshDeserialize, BorshSerialize)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] + +#[near(serializers=[json, borsh], contract_state)] pub struct MissionControl { account: Account, agents: HashMap, rates: HashMap, } -#[near_bindgen] +#[near] impl MissionControl { pub fn add_agent(&mut self) { let account_id = env::signer_account_id(); diff --git a/examples/mission-control/src/rate.rs b/examples/mission-control/src/rate.rs index 1d49234c1..7390d69f4 100644 --- a/examples/mission-control/src/rate.rs +++ b/examples/mission-control/src/rate.rs @@ -1,12 +1,10 @@ use crate::account::*; use crate::asset::*; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; use std::collections::HashMap; +use near_sdk::near; -#[derive(PartialEq, Eq, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[derive(PartialEq, Eq)] +#[near(serializers = [json, borsh])] pub struct Rate { pub credit: HashMap, pub debit: HashMap, diff --git a/examples/non-fungible-token/nft/src/lib.rs b/examples/non-fungible-token/nft/src/lib.rs index da8192545..33c0ce5fe 100644 --- a/examples/non-fungible-token/nft/src/lib.rs +++ b/examples/non-fungible-token/nft/src/lib.rs @@ -25,17 +25,15 @@ use near_contract_standards::non_fungible_token::metadata::{ }; use near_contract_standards::non_fungible_token::NonFungibleToken; use near_contract_standards::non_fungible_token::{Token, TokenId}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::collections::LazyOption; use near_sdk::json_types::U128; use near_sdk::{ - env, near_bindgen, require, AccountId, BorshStorageKey, PanicOnDefault, Promise, PromiseOrValue, + env, near, require, AccountId, BorshStorageKey, PanicOnDefault, Promise, PromiseOrValue, }; use std::collections::HashMap; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(PanicOnDefault)] +#[near(contract_state)] pub struct Contract { tokens: NonFungibleToken, metadata: LazyOption, @@ -43,8 +41,8 @@ pub struct Contract { const DATA_IMAGE_SVG_NEAR_ICON: &str = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 288 288'%3E%3Cg id='l' data-name='l'%3E%3Cpath d='M187.58,79.81l-30.1,44.69a3.2,3.2,0,0,0,4.75,4.2L191.86,103a1.2,1.2,0,0,1,2,.91v80.46a1.2,1.2,0,0,1-2.12.77L102.18,77.93A15.35,15.35,0,0,0,90.47,72.5H87.34A15.34,15.34,0,0,0,72,87.84V201.16A15.34,15.34,0,0,0,87.34,216.5h0a15.35,15.35,0,0,0,13.08-7.31l30.1-44.69a3.2,3.2,0,0,0-4.75-4.2L96.14,186a1.2,1.2,0,0,1-2-.91V104.61a1.2,1.2,0,0,1,2.12-.77l89.55,107.23a15.35,15.35,0,0,0,11.71,5.43h3.13A15.34,15.34,0,0,0,216,201.16V87.84A15.34,15.34,0,0,0,200.66,72.5h0A15.35,15.35,0,0,0,187.58,79.81Z'/%3E%3C/g%3E%3C/svg%3E"; -#[derive(BorshSerialize, BorshStorageKey)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(BorshStorageKey)] +#[near] enum StorageKey { NonFungibleToken, Metadata, @@ -53,7 +51,7 @@ enum StorageKey { Approval, } -#[near_bindgen] +#[near] impl Contract { /// Initializes the contract owned by `owner_id` with /// default metadata (for example purposes only). @@ -109,7 +107,7 @@ impl Contract { } } -#[near_bindgen] +#[near] impl NonFungibleTokenCore for Contract { #[payable] fn nft_transfer( @@ -139,7 +137,7 @@ impl NonFungibleTokenCore for Contract { } } -#[near_bindgen] +#[near] impl NonFungibleTokenResolver for Contract { #[private] fn nft_resolve_transfer( @@ -158,7 +156,7 @@ impl NonFungibleTokenResolver for Contract { } } -#[near_bindgen] +#[near] impl NonFungibleTokenApproval for Contract { #[payable] fn nft_approve( @@ -190,7 +188,7 @@ impl NonFungibleTokenApproval for Contract { } } -#[near_bindgen] +#[near] impl NonFungibleTokenEnumeration for Contract { fn nft_total_supply(&self) -> U128 { self.tokens.nft_total_supply() @@ -214,7 +212,7 @@ impl NonFungibleTokenEnumeration for Contract { } } -#[near_bindgen] +#[near] impl NonFungibleTokenMetadataProvider for Contract { fn nft_metadata(&self) -> NFTContractMetadata { self.metadata.get().unwrap() diff --git a/examples/non-fungible-token/test-approval-receiver/src/lib.rs b/examples/non-fungible-token/test-approval-receiver/src/lib.rs index 3c01d03fb..be476226e 100644 --- a/examples/non-fungible-token/test-approval-receiver/src/lib.rs +++ b/examples/non-fungible-token/test-approval-receiver/src/lib.rs @@ -3,15 +3,13 @@ A stub contract that implements nft_on_approve for e2e testing nft_approve. */ use near_contract_standards::non_fungible_token::approval::NonFungibleTokenApprovalReceiver; use near_contract_standards::non_fungible_token::TokenId; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::{env, log, near_bindgen, require, AccountId, Gas, PanicOnDefault, PromiseOrValue}; +use near_sdk::{env, log, near, require, AccountId, Gas, PanicOnDefault, PromiseOrValue}; /// It is estimated that we need to attach 5 TGas for the code execution and 5 TGas for cross-contract call const GAS_FOR_NFT_ON_APPROVE: Gas = Gas::from_tgas(10); -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] +#[derive(PanicOnDefault)] pub struct ApprovalReceiver { non_fungible_token_account_id: AccountId, } @@ -21,7 +19,7 @@ trait ValueReturnTrait { fn ok_go(&self, msg: String) -> PromiseOrValue; } -#[near_bindgen] +#[near] impl ApprovalReceiver { #[init] pub fn new(non_fungible_token_account_id: AccountId) -> Self { @@ -29,7 +27,7 @@ impl ApprovalReceiver { } } -#[near_bindgen] +#[near] impl NonFungibleTokenApprovalReceiver for ApprovalReceiver { /// Could do anything useful to the approval-receiving contract, such as store the given /// approval_id for use later when calling the NFT contract. Can also return whatever it wants, @@ -70,7 +68,7 @@ impl NonFungibleTokenApprovalReceiver for ApprovalReceiver { } } -#[near_bindgen] +#[near] impl ValueReturnTrait for ApprovalReceiver { fn ok_go(&self, msg: String) -> PromiseOrValue { log!("in ok_go, msg={}", msg); diff --git a/examples/non-fungible-token/test-token-receiver/src/lib.rs b/examples/non-fungible-token/test-token-receiver/src/lib.rs index 3c0350f17..142d2c4b5 100644 --- a/examples/non-fungible-token/test-token-receiver/src/lib.rs +++ b/examples/non-fungible-token/test-token-receiver/src/lib.rs @@ -3,15 +3,13 @@ A stub contract that implements nft_on_transfer for simulation testing nft_trans */ use near_contract_standards::non_fungible_token::core::NonFungibleTokenReceiver; use near_contract_standards::non_fungible_token::TokenId; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::{env, log, near_bindgen, require, AccountId, Gas, PanicOnDefault, PromiseOrValue}; +use near_sdk::{env, log, near, require, AccountId, Gas, PanicOnDefault, PromiseOrValue}; /// It is estimated that we need to attach 5 TGas for the code execution and 5 TGas for cross-contract call const GAS_FOR_NFT_ON_TRANSFER: Gas = Gas::from_tgas(10); -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] +#[derive(PanicOnDefault)] pub struct TokenReceiver { non_fungible_token_account_id: AccountId, } @@ -21,7 +19,7 @@ trait ValueReturnTrait { fn ok_go(&self, return_it: bool) -> PromiseOrValue; } -#[near_bindgen] +#[near] impl TokenReceiver { #[init] pub fn new(non_fungible_token_account_id: AccountId) -> Self { @@ -29,7 +27,7 @@ impl TokenReceiver { } } -#[near_bindgen] +#[near] impl NonFungibleTokenReceiver for TokenReceiver { /// Returns true if token should be returned to `sender_id` /// Four supported `msg`s: @@ -81,7 +79,7 @@ impl NonFungibleTokenReceiver for TokenReceiver { } } -#[near_bindgen] +#[near] impl ValueReturnTrait for TokenReceiver { fn ok_go(&self, return_it: bool) -> PromiseOrValue { log!("in ok_go, return_it={}", return_it); diff --git a/examples/status-message/src/lib.rs b/examples/status-message/src/lib.rs index 6283a0f1d..142c68598 100644 --- a/examples/status-message/src/lib.rs +++ b/examples/status-message/src/lib.rs @@ -1,14 +1,11 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::store::LookupMap; -use near_sdk::{env, log, near_bindgen, AccountId, BorshStorageKey}; +use near_sdk::{env, log, near, AccountId, BorshStorageKey}; -#[derive(BorshSerialize, BorshStorageKey)] -#[borsh(crate = "near_sdk::borsh")] +#[derive(BorshStorageKey)] +#[near] struct RecordsKey; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] pub struct StatusMessage { records: LookupMap, } @@ -19,7 +16,7 @@ impl Default for StatusMessage { } } -#[near_bindgen] +#[near] impl StatusMessage { #[payable] pub fn set_status(&mut self, message: String) { @@ -54,7 +51,7 @@ mod tests { testing_env!(context); let mut contract = StatusMessage::default(); contract.set_status("hello".to_string()); - // Flush the pending changes to avoid panic in the view method below due to the pending non-commited changes to the `store::LookupMap`: + // Flush the pending changes to avoid panic in the view method below due to the pending non-committed changes to the `store::LookupMap`: // HostError(ProhibitedInView { method_name: "storage_write" }) contract.records.flush(); assert_eq!(get_logs(), vec!["bob_near set_status with message hello"]); diff --git a/examples/test-contract/src/lib.rs b/examples/test-contract/src/lib.rs index 611a7b3b9..46444f9fc 100644 --- a/examples/test-contract/src/lib.rs +++ b/examples/test-contract/src/lib.rs @@ -1,9 +1,6 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::{env, near_bindgen}; +use near_sdk::{env, near}; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] pub struct TestContract {} impl Default for TestContract { @@ -12,7 +9,7 @@ impl Default for TestContract { } } -#[near_bindgen] +#[near] impl TestContract { #[init] pub fn new() -> Self { @@ -21,8 +18,7 @@ impl TestContract { #[init(ignore_state)] pub fn migrate_state() -> Self { - #[derive(BorshDeserialize)] - #[borsh(crate = "near_sdk::borsh")] + #[near] struct OldContract { // ... } diff --git a/examples/versioned/src/lib.rs b/examples/versioned/src/lib.rs index c3019396e..36a81b524 100644 --- a/examples/versioned/src/lib.rs +++ b/examples/versioned/src/lib.rs @@ -1,13 +1,10 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::store::UnorderedMap; -use near_sdk::{env, log, near_bindgen, AccountId, NearToken}; +use near_sdk::{env, log, near, AccountId, NearToken}; /// An example of a versioned contract. This is a simple contract that tracks how much /// each account deposits into the contract. In v1, a nonce is added to state which increments /// after each successful deposit. -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near(contract_state)] pub enum VersionedContract { V0(ContractV0), V1(Contract), @@ -47,8 +44,7 @@ impl Default for VersionedContract { } } -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near] pub struct ContractV0 { funders: UnorderedMap, } @@ -59,8 +55,7 @@ impl Default for ContractV0 { } } -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near] pub struct Contract { funders: UnorderedMap, nonce: u64, @@ -72,7 +67,7 @@ impl Default for Contract { } } -#[near_bindgen] +#[near] impl VersionedContract { #[payable] pub fn deposit(&mut self) { diff --git a/near-contract-standards/CHANGELOG.md b/near-contract-standards/CHANGELOG.md index eb911190a..92a604d30 100644 --- a/near-contract-standards/CHANGELOG.md +++ b/near-contract-standards/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [5.1.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.0.0...near-contract-standards-v5.1.0) - 2024-03-28 + +### Added +- Finalize `#[near]` attribute-macro implementation with the support for custom parameters passing to serializer attributes `#[near(serializers = [borsh(...)])]` ([#1158](https://github.com/near/near-sdk-rs/pull/1158)) +- Introduce `#[near]` macro to further streamline contracts development reducing the boilerplate! ([#1142](https://github.com/near/near-sdk-rs/pull/1142)) + ## [5.0.0-alpha.3](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.0.0-alpha.2...near-contract-standards-v5.0.0-alpha.3) - 2024-02-19 ### Fixed diff --git a/near-contract-standards/Cargo.toml b/near-contract-standards/Cargo.toml index e6677b2de..86901c5f9 100644 --- a/near-contract-standards/Cargo.toml +++ b/near-contract-standards/Cargo.toml @@ -13,7 +13,7 @@ NEAR smart contracts standard library. """ [dependencies] -near-sdk = { path = "../near-sdk", version = "~5.0.0", default-features = false, features = ["legacy"] } +near-sdk = { path = "../near-sdk", version = "~5.1.0", default-features = false, features = ["legacy"] } [dev-dependencies] near-sdk = { path = "../near-sdk", default-features = false, features = ["unit-testing"] } diff --git a/near-contract-standards/src/fungible_token/core.rs b/near-contract-standards/src/fungible_token/core.rs index 93bece6d8..defe0752c 100644 --- a/near-contract-standards/src/fungible_token/core.rs +++ b/near-contract-standards/src/fungible_token/core.rs @@ -8,22 +8,20 @@ use near_sdk::PromiseOrValue; /// # Examples /// /// ``` -/// use near_sdk::{near_bindgen, PanicOnDefault, AccountId, PromiseOrValue}; -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; +/// use near_sdk::{near, PanicOnDefault, AccountId, PromiseOrValue}; /// use near_sdk::collections::LazyOption; /// use near_sdk::json_types::U128; /// use near_contract_standards::fungible_token::{FungibleToken, FungibleTokenCore}; /// use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// token: FungibleToken, /// metadata: LazyOption, /// } /// -/// #[near_bindgen] +/// #[near] /// impl FungibleTokenCore for Contract { /// #[payable] /// fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { diff --git a/near-contract-standards/src/fungible_token/core_impl.rs b/near-contract-standards/src/fungible_token/core_impl.rs index 64e162460..3b3a5aae8 100644 --- a/near-contract-standards/src/fungible_token/core_impl.rs +++ b/near-contract-standards/src/fungible_token/core_impl.rs @@ -2,11 +2,10 @@ use crate::fungible_token::core::FungibleTokenCore; use crate::fungible_token::events::{FtBurn, FtTransfer}; use crate::fungible_token::receiver::ext_ft_receiver; use crate::fungible_token::resolver::{ext_ft_resolver, FungibleTokenResolver}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::collections::LookupMap; use near_sdk::json_types::U128; use near_sdk::{ - assert_one_yocto, env, log, require, AccountId, Gas, IntoStorageKey, PromiseOrValue, + assert_one_yocto, env, log, near, require, AccountId, Gas, IntoStorageKey, PromiseOrValue, PromiseResult, StorageUsage, }; @@ -26,8 +25,7 @@ pub type Balance = u128; /// - AccountRegistrar -- interface for an account to register and unregister /// /// For example usage, see examples/fungible-token/src/lib.rs. -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near] pub struct FungibleToken { /// AccountID -> Account balance. pub accounts: LookupMap, diff --git a/near-contract-standards/src/fungible_token/macros.rs b/near-contract-standards/src/fungible_token/macros.rs index 1092923ec..12d210f69 100644 --- a/near-contract-standards/src/fungible_token/macros.rs +++ b/near-contract-standards/src/fungible_token/macros.rs @@ -9,7 +9,7 @@ macro_rules! impl_fungible_token_core { use $crate::fungible_token::core::FungibleTokenCore; use $crate::fungible_token::resolver::FungibleTokenResolver; - #[near_bindgen] + #[near] impl FungibleTokenCore for $contract { #[payable] fn ft_transfer( @@ -41,7 +41,7 @@ macro_rules! impl_fungible_token_core { } } - #[near_bindgen] + #[near] impl FungibleTokenResolver for $contract { #[private] fn ft_resolve_transfer( @@ -76,7 +76,7 @@ macro_rules! impl_fungible_token_storage { StorageManagement, StorageBalance, StorageBalanceBounds }; - #[near_bindgen] + #[near] impl StorageManagement for $contract { #[payable] fn storage_deposit( diff --git a/near-contract-standards/src/fungible_token/metadata.rs b/near-contract-standards/src/fungible_token/metadata.rs index 5269ded39..1eecbbbf9 100644 --- a/near-contract-standards/src/fungible_token/metadata.rs +++ b/near-contract-standards/src/fungible_token/metadata.rs @@ -1,13 +1,10 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::json_types::Base64VecU8; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{ext_contract, require, NearSchema}; +use near_sdk::{ext_contract, near, require}; pub const FT_METADATA_SPEC: &str = "ft-1.0.0"; -#[derive(Clone, BorshDeserialize, BorshSerialize, Deserialize, Serialize, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Clone)] +#[near(serializers=[borsh, json])] pub struct FungibleTokenMetadata { pub spec: String, pub name: String, diff --git a/near-contract-standards/src/fungible_token/resolver.rs b/near-contract-standards/src/fungible_token/resolver.rs index 4fea313fa..ce58dad82 100644 --- a/near-contract-standards/src/fungible_token/resolver.rs +++ b/near-contract-standards/src/fungible_token/resolver.rs @@ -5,22 +5,20 @@ use near_sdk::{ext_contract, json_types::U128, AccountId}; /// # Examples /// /// ``` -/// use near_sdk::{near_bindgen, PanicOnDefault, AccountId, log}; -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; +/// use near_sdk::{near, PanicOnDefault, AccountId, log}; /// use near_sdk::collections::LazyOption; /// use near_sdk::json_types::U128; /// use near_contract_standards::fungible_token::{FungibleToken, FungibleTokenResolver}; /// use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// token: FungibleToken, /// metadata: LazyOption, /// } /// -///#[near_bindgen] +///#[near] /// impl FungibleTokenResolver for Contract { /// #[private] /// fn ft_resolve_transfer( diff --git a/near-contract-standards/src/non_fungible_token/approval/mod.rs b/near-contract-standards/src/non_fungible_token/approval/mod.rs index 3bd2198a8..002091268 100644 --- a/near-contract-standards/src/non_fungible_token/approval/mod.rs +++ b/near-contract-standards/src/non_fungible_token/approval/mod.rs @@ -21,18 +21,16 @@ use near_sdk::Promise; /// /// ``` /// use std::collections::HashMap; -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen, Promise}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near, Promise}; /// use near_contract_standards::non_fungible_token::{TokenId, NonFungibleToken, NonFungibleTokenApproval}; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// tokens: NonFungibleToken, ///} /// -/// #[near_bindgen] +/// #[near] /// impl NonFungibleTokenApproval for Contract { /// #[payable] /// fn nft_approve(&mut self, token_id: TokenId, account_id: AccountId, msg: Option) -> Option { diff --git a/near-contract-standards/src/non_fungible_token/core/core_impl.rs b/near-contract-standards/src/non_fungible_token/core/core_impl.rs index 2bd71f9f0..733daf8f1 100644 --- a/near-contract-standards/src/non_fungible_token/core/core_impl.rs +++ b/near-contract-standards/src/non_fungible_token/core/core_impl.rs @@ -6,11 +6,11 @@ use crate::non_fungible_token::events::{NftMint, NftTransfer}; use crate::non_fungible_token::metadata::TokenMetadata; use crate::non_fungible_token::token::{Token, TokenId}; use crate::non_fungible_token::utils::{refund_approved_account_ids, refund_deposit_to_account}; -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::borsh::BorshSerialize; use near_sdk::collections::{LookupMap, TreeMap, UnorderedSet}; use near_sdk::json_types::Base64VecU8; use near_sdk::{ - assert_one_yocto, env, require, AccountId, BorshStorageKey, Gas, IntoStorageKey, + assert_one_yocto, env, near, require, AccountId, BorshStorageKey, Gas, IntoStorageKey, PromiseOrValue, PromiseResult, StorageUsage, }; use std::collections::HashMap; @@ -28,8 +28,7 @@ const GAS_FOR_NFT_TRANSFER_CALL: Gas = Gas::from_tgas(30); /// - NonFungibleTokenMetadata -- return metadata for the token in NEP-177, up to contract to implement. /// /// For example usage, see examples/non-fungible-token/src/lib.rs. -#[derive(BorshDeserialize, BorshSerialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near] pub struct NonFungibleToken { // owner of contract pub owner_id: AccountId, diff --git a/near-contract-standards/src/non_fungible_token/core/mod.rs b/near-contract-standards/src/non_fungible_token/core/mod.rs index d4e747d74..4c5892bf3 100644 --- a/near-contract-standards/src/non_fungible_token/core/mod.rs +++ b/near-contract-standards/src/non_fungible_token/core/mod.rs @@ -23,17 +23,15 @@ use near_sdk::PromiseOrValue; /// # Examples /// /// ``` -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near}; /// use near_contract_standards::non_fungible_token::{core::NonFungibleTokenCore, NonFungibleToken, TokenId, Token}; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// tokens: NonFungibleToken, ///} -/// #[near_bindgen] +/// #[near] /// impl NonFungibleTokenCore for Contract { /// #[payable] /// fn nft_transfer(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option) { diff --git a/near-contract-standards/src/non_fungible_token/core/resolver.rs b/near-contract-standards/src/non_fungible_token/core/resolver.rs index 821335690..e43d409dc 100644 --- a/near-contract-standards/src/non_fungible_token/core/resolver.rs +++ b/near-contract-standards/src/non_fungible_token/core/resolver.rs @@ -8,17 +8,15 @@ use std::collections::HashMap; /// /// ``` /// use std::collections::HashMap; -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near}; /// use near_contract_standards::non_fungible_token::{NonFungibleToken, NonFungibleTokenResolver, TokenId}; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// tokens: NonFungibleToken, ///} -/// #[near_bindgen] +/// #[near] /// impl NonFungibleTokenResolver for Contract { /// #[private] /// fn nft_resolve_transfer(&mut self, previous_owner_id: AccountId, receiver_id: AccountId, token_id: TokenId, approved_account_ids: Option>) -> bool { diff --git a/near-contract-standards/src/non_fungible_token/enumeration/mod.rs b/near-contract-standards/src/non_fungible_token/enumeration/mod.rs index 2e82973f8..ba8661551 100644 --- a/near-contract-standards/src/non_fungible_token/enumeration/mod.rs +++ b/near-contract-standards/src/non_fungible_token/enumeration/mod.rs @@ -10,19 +10,17 @@ use near_sdk::AccountId; /// /// ``` /// use std::collections::HashMap; -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near_bindgen, Promise}; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near, Promise}; /// use near_contract_standards::non_fungible_token::{NonFungibleToken, NonFungibleTokenEnumeration, TokenId, Token}; /// use near_sdk::json_types::U128; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// tokens: NonFungibleToken, ///} /// -/// #[near_bindgen] +/// #[near] /// impl NonFungibleTokenEnumeration for Contract { /// fn nft_total_supply(&self) -> U128 { /// self.tokens.nft_total_supply() diff --git a/near-contract-standards/src/non_fungible_token/macros.rs b/near-contract-standards/src/non_fungible_token/macros.rs index ecd98045a..e16b8b384 100644 --- a/near-contract-standards/src/non_fungible_token/macros.rs +++ b/near-contract-standards/src/non_fungible_token/macros.rs @@ -9,7 +9,7 @@ macro_rules! impl_non_fungible_token_core { use $crate::non_fungible_token::core::NonFungibleTokenCore; use $crate::non_fungible_token::core::NonFungibleTokenResolver; - #[near_bindgen] + #[near] impl NonFungibleTokenCore for $contract { #[payable] fn nft_transfer( @@ -39,7 +39,7 @@ macro_rules! impl_non_fungible_token_core { } } - #[near_bindgen] + #[near] impl NonFungibleTokenResolver for $contract { #[private] fn nft_resolve_transfer( @@ -70,7 +70,7 @@ macro_rules! impl_non_fungible_token_approval { ($contract: ident, $token: ident) => { use $crate::non_fungible_token::approval::NonFungibleTokenApproval; - #[near_bindgen] + #[near] impl NonFungibleTokenApproval for $contract { #[payable] fn nft_approve( @@ -114,7 +114,7 @@ macro_rules! impl_non_fungible_token_enumeration { ($contract: ident, $token: ident) => { use $crate::non_fungible_token::enumeration::NonFungibleTokenEnumeration; - #[near_bindgen] + #[near] impl NonFungibleTokenEnumeration for $contract { fn nft_total_supply(&self) -> near_sdk::json_types::U128 { self.$token.nft_total_supply() diff --git a/near-contract-standards/src/non_fungible_token/metadata.rs b/near-contract-standards/src/non_fungible_token/metadata.rs index a46d08341..d5dbc9ff3 100644 --- a/near-contract-standards/src/non_fungible_token/metadata.rs +++ b/near-contract-standards/src/non_fungible_token/metadata.rs @@ -1,25 +1,12 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::json_types::Base64VecU8; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{require, NearSchema}; +use near_sdk::{near, require}; /// This spec can be treated like a version of the standard. pub const NFT_METADATA_SPEC: &str = "nft-1.0.0"; /// Metadata for the NFT contract itself. -#[derive( - Clone, - Debug, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - Serialize, - Deserialize, - NearSchema, -)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[derive(Clone, Debug, PartialEq, Eq)] +#[near(serializers=[borsh, json])] pub struct NFTContractMetadata { pub spec: String, // required, essentially a version like "nft-1.0.0" pub name: String, // required, ex. "Mosaics" @@ -30,21 +17,8 @@ pub struct NFTContractMetadata { pub reference_hash: Option, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. } -/// Metadata on the individual token level. -#[derive( - Debug, - Clone, - Default, - PartialEq, - Eq, - Serialize, - Deserialize, - BorshDeserialize, - BorshSerialize, - NearSchema, -)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers=[borsh, json])] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct TokenMetadata { pub title: Option, // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055" pub description: Option, // free-form description diff --git a/near-contract-standards/src/non_fungible_token/token.rs b/near-contract-standards/src/non_fungible_token/token.rs index cd0ebfd44..10d699e92 100644 --- a/near-contract-standards/src/non_fungible_token/token.rs +++ b/near-contract-standards/src/non_fungible_token/token.rs @@ -1,12 +1,14 @@ use crate::non_fungible_token::metadata::TokenMetadata; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema}; +use near_sdk::{ + serde::{Deserialize, Serialize}, + AccountId, NearSchema, +}; use std::collections::HashMap; /// Note that token IDs for NFTs are strings on NEAR. It's still fine to use autoincrementing numbers as unique IDs if desired, but they should be stringified. This is to make IDs more future-proof as chain-agnostic conventions and standards arise, and allows for more flexibility with considerations like bridging NFTs across chains, etc. pub type TokenId = String; /// In this implementation, the Token struct takes two extensions standards (metadata and approval) as optional fields, as they are frequently used in modern NFTs. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, NearSchema)] +#[derive(NearSchema, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[serde(crate = "near_sdk::serde")] pub struct Token { pub token_id: TokenId, diff --git a/near-contract-standards/src/storage_management/mod.rs b/near-contract-standards/src/storage_management/mod.rs index 02146dc54..928fe7dfe 100644 --- a/near-contract-standards/src/storage_management/mod.rs +++ b/near-contract-standards/src/storage_management/mod.rs @@ -1,18 +1,12 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::{AccountId, NearSchema, NearToken}; +use near_sdk::{near, AccountId, NearToken}; -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers=[borsh, json])] pub struct StorageBalance { pub total: NearToken, pub available: NearToken, } -#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, NearSchema)] -#[serde(crate = "near_sdk::serde")] -#[borsh(crate = "near_sdk::borsh")] +#[near(serializers=[borsh, json])] pub struct StorageBalanceBounds { pub min: NearToken, pub max: Option, @@ -27,8 +21,7 @@ pub struct StorageBalanceBounds { /// # Examples /// /// ``` -/// use near_sdk::{near_bindgen, PanicOnDefault, AccountId, NearToken, log}; -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; +/// use near_sdk::{near, PanicOnDefault, AccountId, NearToken, log}; /// use near_sdk::collections::LazyOption; /// use near_sdk::json_types::U128; /// use near_contract_standards::fungible_token::FungibleToken; @@ -37,15 +30,14 @@ pub struct StorageBalanceBounds { /// }; /// use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata; /// -/// #[near_bindgen] -/// #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] -/// #[borsh(crate = "near_sdk::borsh")] +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] /// pub struct Contract { /// token: FungibleToken, /// metadata: LazyOption, /// } /// -/// #[near_bindgen] +/// #[near] /// impl StorageManagement for Contract { /// #[payable] /// fn storage_deposit( diff --git a/near-contract-standards/src/upgrade/mod.rs b/near-contract-standards/src/upgrade/mod.rs index d2029554a..bfcbb9eb0 100644 --- a/near-contract-standards/src/upgrade/mod.rs +++ b/near-contract-standards/src/upgrade/mod.rs @@ -1,6 +1,5 @@ -use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; use near_sdk::json_types::U64; -use near_sdk::{env, require, AccountId, Duration, Promise, Timestamp}; +use near_sdk::{env, near, require, AccountId, Duration, Promise, Timestamp}; type WrappedDuration = U64; @@ -25,8 +24,7 @@ pub trait Upgradable { } } -#[derive(BorshSerialize, BorshDeserialize)] -#[borsh(crate = "near_sdk::borsh")] +#[near] pub struct Upgrade { pub owner: AccountId, pub staging_duration: Duration, diff --git a/near-sdk-macros/src/core_impl/contract_metadata/mod.rs b/near-sdk-macros/src/core_impl/contract_metadata/mod.rs index 69d633602..75a183133 100644 --- a/near-sdk-macros/src/core_impl/contract_metadata/mod.rs +++ b/near-sdk-macros/src/core_impl/contract_metadata/mod.rs @@ -8,13 +8,37 @@ struct MacroConfig { } #[derive(serde::Serialize, Default, FromMeta)] -struct ContractMetadata { +pub(crate) struct ContractMetadata { version: Option, link: Option, #[darling(multiple, rename = "standard")] standards: Vec, } +impl quote::ToTokens for ContractMetadata { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let version = &self.version; + let link = &self.link; + let mut standards = quote! {}; + let standards_vec = &self.standards; + for standard in standards_vec { + let standard_name = &standard.standard; + let standard_version = &standard.version; + standards = quote! { + #standards + standard(standard = #standard_name, version = #standard_version), + }; + } + tokens.extend(quote! { + contract_metadata( + version = #version, + link = #link, + #standards + ) + }) + } +} + #[derive(FromMeta, serde::Serialize)] struct Standard { standard: String, @@ -49,7 +73,7 @@ impl ContractMetadata { } } -/// Allows for the injection of the contract source metadata infomation into the contract code as +/// Allows for the injection of the contract source metadata information into the contract code as /// a constant. pub(crate) fn contract_source_metadata_const(attr: proc_macro::TokenStream) -> TokenStream { if attr.to_string().is_empty() { diff --git a/near-sdk-macros/src/core_impl/info_extractor/arg_info.rs b/near-sdk-macros/src/core_impl/info_extractor/arg_info.rs index 150a8632b..2f40f2972 100644 --- a/near-sdk-macros/src/core_impl/info_extractor/arg_info.rs +++ b/near-sdk-macros/src/core_impl/info_extractor/arg_info.rs @@ -35,7 +35,7 @@ pub struct ArgInfo { pub bindgen_ty: BindgenArgType, /// Type of serializer that we use for this argument. pub serializer_ty: SerializerType, - /// Spans of all occurences of the `Self` token, if any. + /// Spans of all occurrences of the `Self` token, if any. pub self_occurrences: Vec, /// The original `PatType` of the argument. pub original: PatType, diff --git a/near-sdk-macros/src/core_impl/mod.rs b/near-sdk-macros/src/core_impl/mod.rs index 80d77fab2..4f0dcd0c4 100644 --- a/near-sdk-macros/src/core_impl/mod.rs +++ b/near-sdk-macros/src/core_impl/mod.rs @@ -7,5 +7,6 @@ mod info_extractor; mod utils; pub(crate) use code_generator::*; pub(crate) use contract_metadata::contract_source_metadata_const; +pub(crate) use contract_metadata::ContractMetadata; pub(crate) use event::{get_event_version, near_events}; pub(crate) use info_extractor::*; diff --git a/near-sdk-macros/src/lib.rs b/near-sdk-macros/src/lib.rs index c6a4c105f..899efa4a5 100644 --- a/near-sdk-macros/src/lib.rs +++ b/near-sdk-macros/src/lib.rs @@ -8,9 +8,232 @@ use core_impl::{ext::generate_ext_structs, metadata::generate_contract_metadata_ use proc_macro::TokenStream; use self::core_impl::*; +use darling::ast::NestedMeta; +use darling::{Error, FromMeta}; use proc_macro2::{Ident, Span}; use quote::{quote, ToTokens}; -use syn::{parse_quote, ImplItem, ItemEnum, ItemImpl, ItemStruct, ItemTrait, WhereClause}; +use syn::{parse_quote, Expr, ImplItem, ItemEnum, ItemImpl, ItemStruct, ItemTrait, WhereClause}; + +#[derive(Debug, Clone)] +struct Serializers { + vec: Vec, +} + +impl FromMeta for Serializers { + fn from_expr(expr: &syn::Expr) -> Result { + match expr { + syn::Expr::Array(expr_array) => Ok(Serializers { + vec: expr_array + .elems + .iter() + .map(::from_expr) + .map(|x| x.unwrap()) + .collect::>(), + }), + _ => Err(Error::unexpected_expr_type(expr)), + } + } +} + +#[derive(FromMeta)] +struct NearMacroArgs { + serializers: Option, + contract_state: Option, + contract_metadata: Option, + inside_nearsdk: Option, +} + +/// This attribute macro is used to enhance the near_bindgen macro. +/// It is used to add Borsh and Serde derives for serialization and deserialization. +/// It also adds `BorshSchema` and `JsonSchema` if needed +/// +/// If you would like to add Borsh or Serde serialization and deserialization to your contract, +/// you can use the abi attribute and pass in the serializers you would like to use. +/// +/// # Example +/// +/// ```ignore +/// #[near(serializers=[borsh, json])] +/// struct MyStruct { +/// pub name: String, +/// } +/// ``` +/// effectively becomes: +/// ```ignore +/// use borsh::{BorshSerialize, BorshDeserialize}; +/// use serde::{Serialize, Deserialize}; +/// use near_sdk_macro::NearSchema; +/// #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, NearSchema)] +/// #[borsh(crate = "near_sdk::borsh")] +/// #[serde(crate = "near_sdk::serde")] +/// struct MyStruct { +/// pub name: String, +/// } +/// ``` +/// Please note that `BorshSchema` and `JsonSchema` are added inside NearSchema whenever you use near macro for struct or enum. +/// By default, if no serializers are passed, Borsh is used. +/// +/// If you want this struct to be a contract state, you can pass in the contract_state argument. +/// +/// # Example +/// ```ignore +/// #[near(contract_state)] +/// struct MyStruct { +/// pub name: String, +/// } +/// ``` +/// becomes: +/// ```ignore +/// #[near_bindgen] +/// #[derive(BorshSerialize, BorshDeserialize, NearSchema)] +/// #[borsh(crate = "near_sdk::borsh")] +/// struct MyStruct { +/// pub name: String, +/// } +/// ``` +/// +/// As well, the macro supports arguments like `event_json` and `contract_metadata`. +/// +#[proc_macro_attribute] +pub fn near(attr: TokenStream, item: TokenStream) -> TokenStream { + if attr.to_string().contains("event_json") { + return core_impl::near_events(attr, item); + } + + let meta_list = match NestedMeta::parse_meta_list(attr.into()) { + Ok(v) => v, + Err(e) => { + return TokenStream::from(Error::from(e).write_errors()); + } + }; + + let near_macro_args = match NearMacroArgs::from_list(&meta_list) { + Ok(v) => v, + Err(e) => { + return TokenStream::from(e.write_errors()); + } + }; + + let near_sdk_crate = if near_macro_args.inside_nearsdk.unwrap_or(false) { + quote! {crate} + } else { + quote! {::near_sdk} + }; + let string_borsh_crate = quote! {#near_sdk_crate::borsh}.to_string(); + let string_serde_crate = quote! {#near_sdk_crate::serde}.to_string(); + + let mut expanded: proc_macro2::TokenStream = quote! {}; + + if near_macro_args.contract_state.unwrap_or(false) { + if let Some(metadata) = near_macro_args.contract_metadata { + expanded = quote! {#[#near_sdk_crate::near_bindgen(#metadata)]} + } else { + expanded = quote! {#[#near_sdk_crate::near_bindgen]} + } + }; + + let mut has_borsh = false; + let mut has_json = false; + + let mut borsh_attr = quote! {}; + + match near_macro_args.serializers { + Some(serializers) => { + let attr2 = serializers.clone(); + + attr2.vec.iter().for_each(|old_expr| { + let new_expr = &mut old_expr.clone(); + match &mut *new_expr { + Expr::Call(ref mut call_expr) => { + if let Expr::Path(ref mut path) = &mut *call_expr.func { + if let Some(ident) = path.path.get_ident() { + if *ident == "json" { + has_json = true; + path.path = + syn::Path::from(Ident::new("serde", Span::call_site())); + call_expr.args.push(parse_quote! {crate=#string_serde_crate}); + } else if *ident == "borsh" { + has_borsh = true; + call_expr.args.push(parse_quote! {crate=#string_borsh_crate}); + } + } + } + borsh_attr = quote! {#[#new_expr]}; + } + Expr::Path(ref mut path_expr) => { + if let Some(ident) = path_expr.path.get_ident() { + if *ident == "json" { + has_json = true; + } + if *ident == "borsh" { + has_borsh = true; + borsh_attr = quote! {#[borsh(crate=#string_borsh_crate)]}; + } + } + } + _ => {} + } + }); + } + None => { + has_borsh = true; + borsh_attr = quote! {#[borsh(crate = #string_borsh_crate)]}; + } + } + + #[cfg(feature = "abi")] + { + let schema_derive: proc_macro2::TokenStream = + get_schema_derive(has_json, has_borsh, near_sdk_crate.clone(), false); + expanded = quote! { + #expanded + #schema_derive + }; + } + + if has_borsh { + expanded = quote! { + #expanded + #[derive(#near_sdk_crate::borsh::BorshSerialize, #near_sdk_crate::borsh::BorshDeserialize)] + #borsh_attr + }; + } + + if has_json { + expanded = quote! { + #expanded + #[derive(#near_sdk_crate::serde::Serialize, #near_sdk_crate::serde::Deserialize)] + #[serde(crate = #string_serde_crate)] + }; + } + + if let Ok(input) = syn::parse::(item.clone()) { + expanded = quote! { + #expanded + #input + }; + } else if let Ok(input) = syn::parse::(item.clone()) { + expanded = quote! { + #expanded + #input + }; + } else if let Ok(input) = syn::parse::(item) { + expanded = quote! { + #[#near_sdk_crate::near_bindgen] + #input + }; + } else { + return TokenStream::from( + syn::Error::new( + Span::call_site(), + "near macro can only be used on struct or enum definition and impl sections.", + ) + .to_compile_error(), + ); + } + + TokenStream::from(expanded) +} /// This attribute macro is used on a struct and its implementations /// to generate the necessary code to expose `pub` methods from the contract as well @@ -329,7 +552,7 @@ struct DeriveNearSchema { borsh: Option, } -#[proc_macro_derive(NearSchema, attributes(abi, serde, borsh, schemars, validate))] +#[proc_macro_derive(NearSchema, attributes(abi, serde, borsh, schemars, validate, inside_nearsdk))] pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { #[cfg(not(feature = "abi"))] { @@ -341,6 +564,7 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { use darling::FromDeriveInput; let derive_input = syn::parse_macro_input!(input as syn::DeriveInput); + let generics = derive_input.generics.clone(); let args = match DeriveNearSchema::from_derive_input(&derive_input) { Ok(v) => v, Err(e) => { @@ -350,7 +574,7 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { if args.borsh.is_none() && args.json.is_none() - && derive_input.attrs.iter().any(|attr| attr.path().is_ident("abi")) + && derive_input.clone().attrs.iter().any(|attr| attr.path().is_ident("abi")) { return TokenStream::from( syn::Error::new_spanned( @@ -363,7 +587,7 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { // #[abi(json, borsh)] let (json_schema, borsh_schema) = (args.json.unwrap_or(false), args.borsh.unwrap_or(false)); - let mut input = derive_input; + let mut input = derive_input.clone(); input.attrs = args.attrs; let strip_unknown_attr = |attrs: &mut Vec| { @@ -399,41 +623,37 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { } } + let near_sdk_crate = + if derive_input.attrs.iter().any(|attr| attr.path().is_ident("inside_nearsdk")) { + quote! {crate} + } else { + quote! {::near_sdk} + }; + // or #[abi(json)] let json_schema = json_schema || !borsh_schema; - let derive = { - let mut derive = quote! {}; - if borsh_schema { - derive = quote! { - #[derive(::near_sdk::borsh::BorshSchema)] - #[borsh(crate = "::near_sdk::borsh")] - }; - } - if json_schema { - derive = quote! { - #derive - #[derive(::near_sdk::schemars::JsonSchema)] - #[schemars(crate = "::near_sdk::schemars")] - }; - } - derive - }; + let derive = get_schema_derive(json_schema, borsh_schema, near_sdk_crate.clone(), true); let input_ident = &input.ident; let input_ident_proxy = quote::format_ident!("{}__NEAR_SCHEMA_PROXY", input_ident); let json_impl = if json_schema { + let where_clause = get_where_clause( + &generics, + input_ident, + quote! {#near_sdk_crate::schemars::JsonSchema}, + ); quote! { #[automatically_derived] - impl ::near_sdk::schemars::JsonSchema for #input_ident_proxy { + impl #generics #near_sdk_crate::schemars::JsonSchema for #input_ident_proxy #generics #where_clause { fn schema_name() -> ::std::string::String { - stringify!(#input_ident).to_string() + stringify!(#input_ident #generics).to_string() } - fn json_schema(gen: &mut ::near_sdk::schemars::gen::SchemaGenerator) -> ::near_sdk::schemars::schema::Schema { - <#input_ident as ::near_sdk::schemars::JsonSchema>::json_schema(gen) + fn json_schema(gen: &mut #near_sdk_crate::schemars::gen::SchemaGenerator) -> #near_sdk_crate::schemars::schema::Schema { + <#input_ident #generics as #near_sdk_crate::schemars::JsonSchema>::json_schema(gen) } } } @@ -442,20 +662,25 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { }; let borsh_impl = if borsh_schema { + let where_clause = get_where_clause( + &generics, + input_ident, + quote! {#near_sdk_crate::borsh::BorshSchema}, + ); quote! { #[automatically_derived] - impl ::near_sdk::borsh::BorshSchema for #input_ident_proxy { - fn declaration() -> ::near_sdk::borsh::schema::Declaration { - stringify!(#input_ident).to_string() + impl #generics #near_sdk_crate::borsh::BorshSchema for #input_ident_proxy #generics #where_clause { + fn declaration() -> #near_sdk_crate::borsh::schema::Declaration { + stringify!(#input_ident #generics).to_string() } fn add_definitions_recursively( - definitions: &mut ::near_sdk::borsh::__private::maybestd::collections::BTreeMap< - ::near_sdk::borsh::schema::Declaration, - ::near_sdk::borsh::schema::Definition + definitions: &mut #near_sdk_crate::borsh::__private::maybestd::collections::BTreeMap< + #near_sdk_crate::borsh::schema::Declaration, + #near_sdk_crate::borsh::schema::Definition >, ) { - <#input_ident as ::near_sdk::borsh::BorshSchema>::add_definitions_recursively(definitions); + <#input_ident #generics as #near_sdk_crate::borsh::BorshSchema>::add_definitions_recursively(definitions); } } } @@ -467,9 +692,10 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { #[cfg(not(target_arch = "wasm32"))] const _: () = { #[allow(non_camel_case_types)] - type #input_ident_proxy = #input_ident; + type #input_ident_proxy #generics = #input_ident #generics; { #derive + #[allow(dead_code)] #input #json_impl @@ -480,6 +706,57 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream { } } +#[allow(dead_code)] +fn get_schema_derive( + json_schema: bool, + borsh_schema: bool, + near_sdk_crate: proc_macro2::TokenStream, + need_borsh_crate: bool, +) -> proc_macro2::TokenStream { + let string_borsh_crate = quote! {#near_sdk_crate::borsh}.to_string(); + let string_schemars_crate = quote! {#near_sdk_crate::schemars}.to_string(); + + let mut derive = quote! {}; + if borsh_schema { + derive = quote! { + #[cfg_attr(not(target_arch = "wasm32"), derive(#near_sdk_crate::borsh::BorshSchema))] + }; + if need_borsh_crate { + derive = quote! { + #derive + #[cfg_attr(not(target_arch = "wasm32"), borsh(crate = #string_borsh_crate))] + }; + } + } + if json_schema { + derive = quote! { + #derive + #[cfg_attr(not(target_arch = "wasm32"), derive(#near_sdk_crate::schemars::JsonSchema))] + #[cfg_attr(not(target_arch = "wasm32"), schemars(crate = #string_schemars_crate))] + }; + } + derive +} + +#[cfg(feature = "abi")] +fn get_where_clause( + generics: &syn::Generics, + input_ident: &syn::Ident, + trait_name: proc_macro2::TokenStream, +) -> WhereClause { + let (_, ty_generics, where_clause) = generics.split_for_impl(); + + let predicate = parse_quote!(#input_ident #ty_generics: #trait_name); + + let where_clause: WhereClause = if let Some(mut w) = where_clause.cloned() { + w.predicates.push(predicate); + w + } else { + parse_quote!(where #predicate) + }; + where_clause +} + /// `PanicOnDefault` generates implementation for `Default` trait that panics with the following /// message `The contract is not initialized` when `default()` is called. /// This is a helpful macro in case the contract is required to be initialized with either `init` or diff --git a/near-sdk/Cargo.toml b/near-sdk/Cargo.toml index bdcacd058..7488fe7bd 100644 --- a/near-sdk/Cargo.toml +++ b/near-sdk/Cargo.toml @@ -21,7 +21,7 @@ required-features = ["abi", "unstable"] # Provide near_bidgen macros. serde = { version = "1", features = ["derive"] } serde_json = "1" -near-sdk-macros = { path = "../near-sdk-macros", version = "~5.0.0" } +near-sdk-macros = { path = "../near-sdk-macros", version = "~5.1.0" } near-sys = { path = "../near-sys", version = "0.2.1" } base64 = "0.21" borsh = { version = "1.0.0", features = ["derive"] } diff --git a/near-sdk/compilation_tests/all.rs b/near-sdk/compilation_tests/all.rs index e78f316e2..baad7f804 100644 --- a/near-sdk/compilation_tests/all.rs +++ b/near-sdk/compilation_tests/all.rs @@ -36,4 +36,5 @@ fn compilation_tests() { t.pass("compilation_tests/contract_metadata.rs"); t.compile_fail("compilation_tests/contract_metadata_fn_name.rs"); t.pass("compilation_tests/contract_metadata_bindgen.rs"); + t.pass("compilation_tests/types.rs"); } diff --git a/near-sdk/compilation_tests/bad_argument.rs b/near-sdk/compilation_tests/bad_argument.rs index f50ad03ec..3eb52b145 100644 --- a/near-sdk/compilation_tests/bad_argument.rs +++ b/near-sdk/compilation_tests/bad_argument.rs @@ -1,31 +1,31 @@ //! Method with non-deserializable argument type. -use near_sdk::near_bindgen; -use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::near; use std::collections::HashMap; -use serde::{Serialize, Deserialize}; -#[derive(BorshSerialize, BorshDeserialize, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Eq, PartialEq, Hash, PartialOrd, Ord)] +#[near(serializers=[borsh, json])] enum TypeA { Var1, Var2 } -#[derive(BorshSerialize, BorshDeserialize, Eq, PartialEq, Hash, PartialOrd, Serialize, Deserialize)] +#[derive(Eq, PartialEq, Hash, PartialOrd)] +#[near(serializers=[borsh, json])] enum TypeB { Var1, Var2 } -#[near_bindgen] -#[derive(Default, BorshSerialize, BorshDeserialize)] +#[near(contract_state)] +#[derive(Default)] struct Storage { map: HashMap } trait MyTrait {} -#[near_bindgen] +#[near] impl Storage { pub fn insert(&mut self, key: TypeA, value: TypeB, t: impl MyTrait) -> Option { self.map.insert(key, value) diff --git a/near-sdk/compilation_tests/borsh_storage_key.rs b/near-sdk/compilation_tests/borsh_storage_key.rs index 72badcdfd..dbfaf039e 100644 --- a/near-sdk/compilation_tests/borsh_storage_key.rs +++ b/near-sdk/compilation_tests/borsh_storage_key.rs @@ -1,8 +1,9 @@ //! Testing BorshStorageKey macro. -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::BorshSerialize; +use near_sdk::near; use near_sdk::collections::LookupMap; -use near_sdk::{near_bindgen, BorshStorageKey}; +use near_sdk::BorshStorageKey; #[derive(BorshStorageKey, BorshSerialize)] struct StorageKeyStruct { @@ -15,8 +16,7 @@ enum StorageKeyEnum { SubAccounts { account_id: String }, } -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] +#[near(contract_state)] struct Contract { map1: LookupMap, map2: LookupMap, @@ -31,7 +31,7 @@ impl Default for Contract { } } -#[near_bindgen] +#[near] impl Contract {} fn main() {} diff --git a/near-sdk/compilation_tests/borsh_storage_key_generics.rs b/near-sdk/compilation_tests/borsh_storage_key_generics.rs index e7a9c311c..714fcdb48 100644 --- a/near-sdk/compilation_tests/borsh_storage_key_generics.rs +++ b/near-sdk/compilation_tests/borsh_storage_key_generics.rs @@ -1,8 +1,9 @@ //! Testing BorshStorageKey macro with lifetimes and generics. -use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::borsh::{self, BorshSerialize}; use near_sdk::collections::LookupMap; -use near_sdk::{near_bindgen, BorshStorageKey}; +use near_sdk::BorshStorageKey; +use near_sdk::near; #[derive(BorshStorageKey, BorshSerialize)] struct StorageKeyStruct<'a, T> @@ -21,8 +22,7 @@ where SubAccounts { account_id: &'a T }, } -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] +#[near(contract_state)] struct Contract { map1: LookupMap, map2: LookupMap, @@ -38,7 +38,7 @@ impl Default for Contract { } } -#[near_bindgen] +#[near] impl Contract {} fn main() {} diff --git a/near-sdk/compilation_tests/complex.rs b/near-sdk/compilation_tests/complex.rs index 6c649b771..24f39cba7 100644 --- a/near-sdk/compilation_tests/complex.rs +++ b/near-sdk/compilation_tests/complex.rs @@ -1,33 +1,33 @@ //! Complex smart contract. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; -use serde::{Deserialize, Serialize}; +use near_sdk::near; use std::collections::HashMap; #[derive( - BorshDeserialize, BorshSerialize, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, + Eq, PartialEq, Hash, PartialOrd, Ord, )] +#[near(serializers=[borsh, json])] pub enum TypeA { Var1, Var2, } #[derive( - BorshDeserialize, BorshSerialize, Eq, PartialEq, Hash, PartialOrd, Serialize, Deserialize, + Eq, PartialEq, Hash, PartialOrd, )] +#[near(serializers=[borsh, json])] pub enum TypeB { Var1, Var2, } -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Storage { map: HashMap, } -#[near_bindgen] +#[near] impl Storage { pub fn insert(&mut self, key: TypeA, value: TypeB) -> Option { self.map.insert(key, value) diff --git a/near-sdk/compilation_tests/cond_compilation.rs b/near-sdk/compilation_tests/cond_compilation.rs index 325bac149..a7e3434dd 100644 --- a/near-sdk/compilation_tests/cond_compilation.rs +++ b/near-sdk/compilation_tests/cond_compilation.rs @@ -1,15 +1,14 @@ //! Rust contract that uses conditional compilation. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { #[cfg(feature = "myfeature")] #[init] diff --git a/near-sdk/compilation_tests/contract_metadata.rs b/near-sdk/compilation_tests/contract_metadata.rs index cccca796e..20d38a7a1 100644 --- a/near-sdk/compilation_tests/contract_metadata.rs +++ b/near-sdk/compilation_tests/contract_metadata.rs @@ -1,6 +1,6 @@ -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen(contract_metadata( +#[near(contract_state, contract_metadata( version = "39f2d2646f2f60e18ab53337501370dc02a5661c", link = "https://github.com/near-examples/nft-tutorial", standard(standard = "nep330", version = "1.1.0"), @@ -9,7 +9,7 @@ use near_sdk::near_bindgen; ))] struct Contract {} -#[near_bindgen] +#[near] impl Contract {} fn main() {} diff --git a/near-sdk/compilation_tests/contract_metadata_bindgen.rs b/near-sdk/compilation_tests/contract_metadata_bindgen.rs index 02d9ab5c3..da9803774 100644 --- a/near-sdk/compilation_tests/contract_metadata_bindgen.rs +++ b/near-sdk/compilation_tests/contract_metadata_bindgen.rs @@ -1,15 +1,15 @@ use near_account_id::AccountIdRef; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] +#[near(contract_state)] struct Contract {} -#[near_bindgen] +#[near] impl Contract { pub fn anything() {} } -#[near_bindgen] +#[near] impl Contract { pub fn anything_else() {} } diff --git a/near-sdk/compilation_tests/contract_metadata_fn_name.rs b/near-sdk/compilation_tests/contract_metadata_fn_name.rs index 3eaec7424..b53c21590 100644 --- a/near-sdk/compilation_tests/contract_metadata_fn_name.rs +++ b/near-sdk/compilation_tests/contract_metadata_fn_name.rs @@ -1,9 +1,9 @@ -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] +#[near(contract_state)] struct Contract {} -#[near_bindgen] +#[near] impl Contract { pub fn contract_source_metadata() {} } diff --git a/near-sdk/compilation_tests/enum_near_bindgen.rs b/near-sdk/compilation_tests/enum_near_bindgen.rs index a60ba84b9..b0c3f4173 100644 --- a/near-sdk/compilation_tests/enum_near_bindgen.rs +++ b/near-sdk/compilation_tests/enum_near_bindgen.rs @@ -1,10 +1,8 @@ //! Testing that state with enum compiles correctly -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] +#[near(contract_state)] enum StateMachine { StateA, StateB, @@ -16,7 +14,7 @@ impl Default for StateMachine { } } -#[near_bindgen] +#[near] impl StateMachine { pub fn swap_state(&mut self) { *self = match self { diff --git a/near-sdk/compilation_tests/function_error.rs b/near-sdk/compilation_tests/function_error.rs index 9a729d016..768d2befd 100644 --- a/near-sdk/compilation_tests/function_error.rs +++ b/near-sdk/compilation_tests/function_error.rs @@ -1,7 +1,8 @@ //! Testing FunctionError macro. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::{near_bindgen, FunctionError}; +use borsh::BorshSerialize; +use near_sdk::FunctionError; +use near_sdk::near; use std::fmt; #[derive(FunctionError, BorshSerialize)] @@ -11,7 +12,7 @@ struct ErrorStruct { impl fmt::Display for ErrorStruct { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "error ocurred: {}", self.message) + write!(f, "error occurred: {}", self.message) } } @@ -30,11 +31,11 @@ impl fmt::Display for ErrorEnum { } } -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, Default)] +#[derive(Default)] +#[near(contract_state)] struct Contract {} -#[near_bindgen] +#[near] impl Contract { #[handle_result] pub fn set(&self, value: String) -> Result { diff --git a/near-sdk/compilation_tests/generic_const_function.rs b/near-sdk/compilation_tests/generic_const_function.rs index f9e1d4abe..22566e46f 100644 --- a/near-sdk/compilation_tests/generic_const_function.rs +++ b/near-sdk/compilation_tests/generic_const_function.rs @@ -1,15 +1,15 @@ //! Functions can't use const generics. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] + +#[derive(Default)] +#[near(contract_state)] struct Ident { value: u32, } -#[near_bindgen] +#[near] impl Ident { pub fn is_ident_const(&self, val: [u32; N]) -> [u32; N] { val diff --git a/near-sdk/compilation_tests/generic_function.rs b/near-sdk/compilation_tests/generic_function.rs index 91e3e1faf..b0fb0c223 100644 --- a/near-sdk/compilation_tests/generic_function.rs +++ b/near-sdk/compilation_tests/generic_function.rs @@ -1,15 +1,15 @@ //! Functions can't use generics. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] + +#[derive(Default)] +#[near(contract_state)] struct Ident { value: u32, } -#[near_bindgen] +#[near] impl Ident { pub fn is_ident(&self, val: T) -> T { val diff --git a/near-sdk/compilation_tests/handle_result_alias.rs b/near-sdk/compilation_tests/handle_result_alias.rs index eda2ae205..a2f660c3e 100644 --- a/near-sdk/compilation_tests/handle_result_alias.rs +++ b/near-sdk/compilation_tests/handle_result_alias.rs @@ -1,15 +1,14 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; type MyResult = Result; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[derive(Default)] +#[near(contract_state)] struct Contract { value: u32, } -#[near_bindgen] +#[near] impl Contract { #[handle_result(aliased)] pub fn fun(&self) -> MyResult { diff --git a/near-sdk/compilation_tests/impl_generic.rs b/near-sdk/compilation_tests/impl_generic.rs index 11f2ec5d7..9a5e90e9a 100644 --- a/near-sdk/compilation_tests/impl_generic.rs +++ b/near-sdk/compilation_tests/impl_generic.rs @@ -1,18 +1,17 @@ //! Impl block has type parameters. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; #[allow(unused_imports)] use std::marker::PhantomData; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Incrementer { value: u32, data: PhantomData, } -#[near_bindgen] +#[near] impl<'a, T: 'a + std::fmt::Display> Incrementer { pub fn inc(&mut self, by: u32) { self.value += by; diff --git a/near-sdk/compilation_tests/impl_generic.stderr b/near-sdk/compilation_tests/impl_generic.stderr index b4850777b..9e45c281c 100644 --- a/near-sdk/compilation_tests/impl_generic.stderr +++ b/near-sdk/compilation_tests/impl_generic.stderr @@ -1,11 +1,11 @@ error: Impl type parameters are not supported for smart contracts. - --> compilation_tests/impl_generic.rs:10:20 - | -10 | struct Incrementer { - | ^ + --> compilation_tests/impl_generic.rs:9:20 + | +9 | struct Incrementer { + | ^ error: Impl type parameters are not supported for smart contracts. - --> compilation_tests/impl_generic.rs:16:6 + --> compilation_tests/impl_generic.rs:15:6 | -16 | impl<'a, T: 'a + std::fmt::Display> Incrementer { +15 | impl<'a, T: 'a + std::fmt::Display> Incrementer { | ^^ diff --git a/near-sdk/compilation_tests/init_function.rs b/near-sdk/compilation_tests/init_function.rs index d5d669dec..8884bd0be 100644 --- a/near-sdk/compilation_tests/init_function.rs +++ b/near-sdk/compilation_tests/init_function.rs @@ -1,15 +1,12 @@ //! Smart contract with initialization function. -use near_sdk::near_bindgen; -use borsh::{BorshDeserialize, BorshSerialize}; - -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] +use near_sdk::near; +#[near(contract_state)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { pub fn inc(&mut self, by: u32) { self.value += by; diff --git a/near-sdk/compilation_tests/init_ignore_state.rs b/near-sdk/compilation_tests/init_ignore_state.rs index 3cce0c987..94563526a 100644 --- a/near-sdk/compilation_tests/init_ignore_state.rs +++ b/near-sdk/compilation_tests/init_ignore_state.rs @@ -1,15 +1,13 @@ //! Smart contract with initialization function. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] +#[near(contract_state)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { pub fn inc(&mut self, by: u32) { self.value += by; diff --git a/near-sdk/compilation_tests/invalid_arg_pat.rs b/near-sdk/compilation_tests/invalid_arg_pat.rs index f0646f8fa..2cde8da98 100644 --- a/near-sdk/compilation_tests/invalid_arg_pat.rs +++ b/near-sdk/compilation_tests/invalid_arg_pat.rs @@ -3,14 +3,14 @@ //faulty_method checks a combination of serialiser and type not not supported //faulty_method1 checks a combination of serialiser and only Identity pattern allowed. //It is not possible to check Identity pattern and Type not supported together. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::{near_bindgen, PanicOnDefault}; +use near_sdk::near; +use near_sdk::PanicOnDefault; -#[near_bindgen] -#[derive(BorshSerialize, BorshDeserialize, PanicOnDefault)] +#[near(contract_state)] +#[derive(PanicOnDefault)] struct Storage {} -#[near_bindgen] +#[near] impl Storage { pub fn faulty_method(&mut self, #[serializer(SomeNonExistentSerializer)] _a: *mut u32) {} pub fn faulty_method1(&mut self, #[serializer(SomeNonExistentSerializer)] (a, b): (u8, u32)) {} diff --git a/near-sdk/compilation_tests/lifetime_method.rs b/near-sdk/compilation_tests/lifetime_method.rs index a3715e880..af8dbbada 100644 --- a/near-sdk/compilation_tests/lifetime_method.rs +++ b/near-sdk/compilation_tests/lifetime_method.rs @@ -1,15 +1,14 @@ //! Method signature uses lifetime. -use near_sdk::near_bindgen; -use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Ident { value: u32, } -#[near_bindgen] +#[near] impl Ident { pub fn is_ident<'a>(&self, other: &'a u32) -> Option<&'a u32> { if *other == self.value { diff --git a/near-sdk/compilation_tests/no_default.rs b/near-sdk/compilation_tests/no_default.rs index b4e754d7b..7d6476c3a 100644 --- a/near-sdk/compilation_tests/no_default.rs +++ b/near-sdk/compilation_tests/no_default.rs @@ -1,15 +1,15 @@ //! Smart contract with initialization function. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::{near_bindgen, PanicOnDefault}; +use near_sdk::near; +use near_sdk::PanicOnDefault; -#[near_bindgen] -#[derive(PanicOnDefault, BorshDeserialize, BorshSerialize)] +#[derive(PanicOnDefault)] +#[near(contract_state)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { pub fn inc(&mut self, by: u32) { self.value += by; diff --git a/near-sdk/compilation_tests/payable_view.rs b/near-sdk/compilation_tests/payable_view.rs index 879107244..4f45fde16 100644 --- a/near-sdk/compilation_tests/payable_view.rs +++ b/near-sdk/compilation_tests/payable_view.rs @@ -1,13 +1,13 @@ //! Payable view are not valid -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] + +#[derive(Default)] +#[near(contract_state)] struct Test {} -#[near_bindgen] +#[near] impl Test { #[payable] pub fn pay(&self) {} diff --git a/near-sdk/compilation_tests/private.rs b/near-sdk/compilation_tests/private.rs index fff60788a..bf7ff7646 100644 --- a/near-sdk/compilation_tests/private.rs +++ b/near-sdk/compilation_tests/private.rs @@ -1,15 +1,14 @@ //! Regular smart contract. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[derive(Default)] +#[near(contract_state)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { #[private] pub fn inc(&mut self, by: u32) { diff --git a/near-sdk/compilation_tests/private_init_method.rs b/near-sdk/compilation_tests/private_init_method.rs index 3060c1713..73fe2b955 100644 --- a/near-sdk/compilation_tests/private_init_method.rs +++ b/near-sdk/compilation_tests/private_init_method.rs @@ -1,16 +1,14 @@ //! Even though it might feel unintuitive, a method can be both private and init. //! See: https://github.com/near/near-sdk-rs/issues/1040#issuecomment-1687126452 -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; +use near_sdk::near; -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize)] +#[near(contract_state)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { #[private] #[init] diff --git a/near-sdk/compilation_tests/references.rs b/near-sdk/compilation_tests/references.rs index e1e424e1d..3947e4ea0 100644 --- a/near-sdk/compilation_tests/references.rs +++ b/near-sdk/compilation_tests/references.rs @@ -1,33 +1,33 @@ //! Method with non-deserializable argument type. -use borsh::{BorshDeserialize, BorshSerialize}; -use near_sdk::near_bindgen; -use serde::{Deserialize, Serialize}; +use near_sdk::near; use std::collections::HashMap; #[derive( - BorshDeserialize, BorshSerialize, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, + Eq, PartialEq, Hash, PartialOrd, Ord, )] +#[near(serializers=[borsh, json])] pub enum TypeA { Var1, Var2, } #[derive( - BorshDeserialize, BorshSerialize, Eq, PartialEq, Hash, PartialOrd, Serialize, Deserialize, + Eq, PartialEq, Hash, PartialOrd )] +#[near(serializers=[borsh, json])] pub enum TypeB { Var1, Var2, } -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Storage { map: HashMap, } -#[near_bindgen] +#[near] impl Storage { pub fn get(&self, key: &TypeA) -> &TypeB { self.map.get(key).unwrap() diff --git a/near-sdk/compilation_tests/regular.rs b/near-sdk/compilation_tests/regular.rs index ffd77d3ec..e0bd271be 100644 --- a/near-sdk/compilation_tests/regular.rs +++ b/near-sdk/compilation_tests/regular.rs @@ -1,15 +1,14 @@ //! Regular smart contract. -use near_sdk::near_bindgen; -use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Incrementer { value: u32, } -#[near_bindgen] +#[near] impl Incrementer { pub fn inc(&mut self, by: u32) { self.value += by; diff --git a/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_arg.rs b/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_arg.rs index 2a19b9533..172070af7 100644 --- a/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_arg.rs +++ b/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_arg.rs @@ -1,15 +1,15 @@ //! Method signature uses Self. -use near_sdk::near_bindgen; -use serde::{Deserialize, Serialize}; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, Serialize, Deserialize)] + +#[derive(Default)] +#[near(contract_state, serializers=[json])] pub struct Ident { value: u32, } -#[near_bindgen] +#[near] impl Ident { pub fn plain_arg(_value: Option, _value2: Self) { unimplemented!() diff --git a/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_return.rs b/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_return.rs index db895613a..1477d99e4 100644 --- a/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_return.rs +++ b/near-sdk/compilation_tests/self_forbidden_in_non_init_fn_return.rs @@ -1,15 +1,15 @@ //! Method signature uses Self. -use near_sdk::near_bindgen; -use serde::{Deserialize, Serialize}; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, Serialize, Deserialize)] + +#[derive(Default)] +#[near(contract_state, serializers=[json])] pub struct Ident { value: u32, } -#[near_bindgen] +#[near] impl Ident { pub fn plain_ret() -> Self { unimplemented!() diff --git a/near-sdk/compilation_tests/self_support.rs b/near-sdk/compilation_tests/self_support.rs index 1a6844bd1..34207c082 100644 --- a/near-sdk/compilation_tests/self_support.rs +++ b/near-sdk/compilation_tests/self_support.rs @@ -1,15 +1,14 @@ //! Method signature uses Self. -use near_sdk::near_bindgen; -use serde::{Deserialize, Serialize}; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, Serialize, Deserialize)] +#[derive(Default)] +#[near(contract_state, serializers=[json])] pub struct Ident { value: u32, } -#[near_bindgen] +#[near] impl Ident { #[init] pub fn plain_arg(_a: Self) -> Self { diff --git a/near-sdk/compilation_tests/trait_impl.rs b/near-sdk/compilation_tests/trait_impl.rs index 3b7b53ae5..8821835df 100644 --- a/near-sdk/compilation_tests/trait_impl.rs +++ b/near-sdk/compilation_tests/trait_impl.rs @@ -1,10 +1,9 @@ //! Smart contract that implements trait. -use near_sdk::near_bindgen; -use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk::near; -#[near_bindgen] -#[derive(Default, BorshDeserialize, BorshSerialize)] +#[near(contract_state)] +#[derive(Default)] struct Incrementer { value: u32, } @@ -13,14 +12,14 @@ pub trait Zeroable { fn set_to_zero(&mut self); } -#[near_bindgen] +#[near] impl Incrementer { pub fn inc(&mut self, by: u32) { self.value += by; } } -#[near_bindgen] +#[near] impl Zeroable for Incrementer { fn set_to_zero(&mut self) { self.value = 0; diff --git a/near-sdk/compilation_tests/types.rs b/near-sdk/compilation_tests/types.rs new file mode 100644 index 000000000..d98258760 --- /dev/null +++ b/near-sdk/compilation_tests/types.rs @@ -0,0 +1,25 @@ +//! Check types from near_sdk. + +use near_sdk::near; +use near_sdk::collections::{LookupMap, LookupSet, TreeMap, UnorderedMap, UnorderedSet, Vector}; +use near_sdk::json_types::Base58CryptoHash; +use near_sdk::store::{Lazy, LazyOption}; +use near_sdk::CurveType; + +#[near(contract_state)] +struct TypesContainer { + lookup_map: LookupMap, + lookup_set: LookupSet, + tree_map: TreeMap, + unordered_map: UnorderedMap, + unordered_set: UnorderedSet, + vector: Vector, + base58_crypto_hash: Base58CryptoHash, + u64_type: near_sdk::json_types::U64, + base64_vec_u8: near_sdk::json_types::Base64VecU8, + lazy: Lazy, + lazy_option: LazyOption, + curve_type: CurveType, +} + +fn main() {} \ No newline at end of file diff --git a/near-sdk/src/collections/lazy_option.rs b/near-sdk/src/collections/lazy_option.rs index 38cca6eee..ad88b3835 100644 --- a/near-sdk/src/collections/lazy_option.rs +++ b/near-sdk/src/collections/lazy_option.rs @@ -9,12 +9,13 @@ use borsh::{to_vec, BorshDeserialize, BorshSerialize}; use crate::env; use crate::IntoStorageKey; +use near_sdk_macros::near; const ERR_VALUE_SERIALIZATION: &str = "Cannot serialize value with Borsh"; const ERR_VALUE_DESERIALIZATION: &str = "Cannot deserialize value with Borsh"; /// An persistent lazy option, that stores a value in the storage. -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct LazyOption { storage_key: Vec, #[borsh(skip)] diff --git a/near-sdk/src/collections/legacy_tree_map.rs b/near-sdk/src/collections/legacy_tree_map.rs index 7909fa3d9..e532a6214 100644 --- a/near-sdk/src/collections/legacy_tree_map.rs +++ b/near-sdk/src/collections/legacy_tree_map.rs @@ -5,6 +5,7 @@ #![allow(deprecated)] use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use std::ops::Bound; use crate::collections::UnorderedMap; @@ -21,14 +22,14 @@ use crate::IntoStorageKey; /// - `range` of K elements: O(Klog(N)) /// #[deprecated(since = "4.1.0", note = "Use near_sdk::collections::TreeMap")] -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct LegacyTreeMap { root: u64, val: UnorderedMap, tree: Vector>, } -#[derive(Clone, BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct Node { id: u64, key: K, // key stored in a node diff --git a/near-sdk/src/collections/lookup_map.rs b/near-sdk/src/collections/lookup_map.rs index 8b6fab299..d699c76b0 100644 --- a/near-sdk/src/collections/lookup_map.rs +++ b/near-sdk/src/collections/lookup_map.rs @@ -7,13 +7,14 @@ use borsh::{to_vec, BorshDeserialize, BorshSerialize}; use crate::collections::append_slice; use crate::{env, IntoStorageKey}; +use near_sdk_macros::near; const ERR_KEY_SERIALIZATION: &str = "Cannot serialize key with Borsh"; const ERR_VALUE_DESERIALIZATION: &str = "Cannot deserialize value with Borsh"; const ERR_VALUE_SERIALIZATION: &str = "Cannot serialize value with Borsh"; /// An non-iterable implementation of a map that stores its content directly on the trie. -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct LookupMap { key_prefix: Vec, #[borsh(skip)] diff --git a/near-sdk/src/collections/lookup_set.rs b/near-sdk/src/collections/lookup_set.rs index b1360a0ea..f120485f9 100644 --- a/near-sdk/src/collections/lookup_set.rs +++ b/near-sdk/src/collections/lookup_set.rs @@ -3,7 +3,8 @@ //! makes this implementation more efficient in the number of reads and writes. use std::marker::PhantomData; -use borsh::{to_vec, BorshDeserialize, BorshSerialize}; +use borsh::{to_vec, BorshSerialize}; +use near_sdk_macros::near; use crate::collections::append_slice; use crate::{env, IntoStorageKey}; @@ -14,7 +15,7 @@ const ERR_ELEMENT_SERIALIZATION: &str = "Cannot serialize element with Borsh"; /// /// This set stores the values under a hash of the set's `prefix` and [`BorshSerialize`] of the /// value. -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct LookupSet { element_prefix: Vec, #[borsh(skip)] diff --git a/near-sdk/src/collections/mod.rs b/near-sdk/src/collections/mod.rs index ba367f18b..12a69df7c 100644 --- a/near-sdk/src/collections/mod.rs +++ b/near-sdk/src/collections/mod.rs @@ -11,11 +11,9 @@ //! //! ``` //! # use std::collections::HashMap; -//! # use borsh::{BorshSerialize, BorshDeserialize}; -//! # use near_sdk_macros::near_bindgen; +//! # use near_sdk_macros::near; //! -//! #[near_bindgen] -//! #[derive(BorshDeserialize, BorshSerialize)] +//! #[near(contract_state)] //! pub struct StatusMessage { //! records: HashMap, //! } @@ -24,19 +22,17 @@ //! The following is an efficient alternative. It will load each element individually only when it is //! read and will save it only when it is written/removed. //! ``` -//! # use borsh::{BorshSerialize, BorshDeserialize}; -//! # use near_sdk_macros::near_bindgen; +//! # use near_sdk_macros::near; //! # use near_sdk::collections::LookupMap; //! -//! #[near_bindgen] -//! #[derive(BorshDeserialize, BorshSerialize)] +//! #[near(contract_state)] //! pub struct StatusMessage { //! records: LookupMap, //! } //! ``` //! //! The efficiency of `LookupMap` comes at the cost, since it has fewer methods than `HashMap` and is not -//! that seemlessly integrated with the rest of the Rust standard library. +//! that seamlessly integrated with the rest of the Rust standard library. mod legacy_tree_map; #[allow(deprecated)] diff --git a/near-sdk/src/collections/tree_map.rs b/near-sdk/src/collections/tree_map.rs index 6f6d950be..82ab4f40a 100644 --- a/near-sdk/src/collections/tree_map.rs +++ b/near-sdk/src/collections/tree_map.rs @@ -4,6 +4,7 @@ use std::ops::Bound; use crate::collections::LookupMap; use crate::collections::{append, Vector}; use crate::{env, IntoStorageKey}; +use near_sdk_macros::near; /// TreeMap based on AVL-tree /// @@ -14,14 +15,16 @@ use crate::{env, IntoStorageKey}; /// - `above`/`below`: O(log(N)) /// - `range` of K elements: O(Klog(N)) /// -#[derive(BorshSerialize, BorshDeserialize)] + +#[near(inside_nearsdk)] pub struct TreeMap { root: u64, val: LookupMap, tree: Vector>, } -#[derive(Clone, BorshSerialize, BorshDeserialize, Debug)] +#[near(inside_nearsdk)] +#[derive(Clone, Debug)] pub struct Node { id: u64, key: K, // key stored in a node diff --git a/near-sdk/src/collections/unordered_map/mod.rs b/near-sdk/src/collections/unordered_map/mod.rs index d9cccd2e9..facc17e58 100644 --- a/near-sdk/src/collections/unordered_map/mod.rs +++ b/near-sdk/src/collections/unordered_map/mod.rs @@ -7,6 +7,7 @@ pub use iter::Iter; use crate::collections::{append, append_slice, Vector}; use crate::{env, IntoStorageKey}; use borsh::{to_vec, BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use std::mem::size_of; const ERR_INCONSISTENT_STATE: &str = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; @@ -15,7 +16,7 @@ const ERR_VALUE_DESERIALIZATION: &str = "Cannot deserialize value with Borsh"; const ERR_VALUE_SERIALIZATION: &str = "Cannot serialize value with Borsh"; /// An iterable implementation of a map that stores its content directly on the trie. -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct UnorderedMap { key_index_prefix: Vec, keys: Vector, diff --git a/near-sdk/src/collections/unordered_set.rs b/near-sdk/src/collections/unordered_set.rs index 70438805d..b6abb2b47 100644 --- a/near-sdk/src/collections/unordered_set.rs +++ b/near-sdk/src/collections/unordered_set.rs @@ -3,13 +3,14 @@ use crate::collections::{append, append_slice, Vector}; use crate::{env, IntoStorageKey}; use borsh::{to_vec, BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use std::mem::size_of; const ERR_INCONSISTENT_STATE: &str = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; const ERR_ELEMENT_SERIALIZATION: &str = "Cannot serialize element with Borsh"; /// An iterable implementation of a set that stores its content directly on the trie. -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct UnorderedSet { element_index_prefix: Vec, elements: Vector, diff --git a/near-sdk/src/collections/vector.rs b/near-sdk/src/collections/vector.rs index 1c8043149..630d8250f 100644 --- a/near-sdk/src/collections/vector.rs +++ b/near-sdk/src/collections/vector.rs @@ -5,6 +5,7 @@ use std::iter::FusedIterator; use std::marker::PhantomData; use borsh::{to_vec, BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use crate::collections::append_slice; use crate::{env, IntoStorageKey}; @@ -20,7 +21,7 @@ fn expect_consistent_state(val: Option) -> T { /// An iterable implementation of vector that stores its content on the trie. /// Uses the following map: index -> element. -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct Vector { len: u64, prefix: Vec, @@ -510,6 +511,7 @@ mod tests { } #[derive(Debug, BorshDeserialize)] + #[allow(dead_code)] struct WithoutBorshSerialize(u64); let deserialize_only_vec = diff --git a/near-sdk/src/environment/env.rs b/near-sdk/src/environment/env.rs index cb8dc633d..f45a30091 100644 --- a/near-sdk/src/environment/env.rs +++ b/near-sdk/src/environment/env.rs @@ -269,13 +269,13 @@ pub fn random_seed() -> Vec { /// ```rust /// use rand::{Rng, SeedableRng}; /// use rand_chacha::ChaCha20Rng; -/// use near_sdk::near_bindgen; +/// use near_sdk::near; /// use near_sdk::env; -/// #[near_bindgen] +/// #[near(contract_state)] /// struct RngExample { /// val: i32, /// } -/// #[near_bindgen] +/// #[near] /// impl RngExample { /// pub fn increment(&mut self) { /// let mut rng = ChaCha20Rng::from_seed(env::random_seed_array()); @@ -292,13 +292,13 @@ pub fn random_seed() -> Vec { /// /// ```rust /// use near_rng::Rng; -/// use near_sdk::near_bindgen; +/// use near_sdk::near; /// use near_sdk::env; -/// #[near_bindgen] +/// #[near(contract_state)] /// struct NearRngExample { /// val: i32, /// } -/// #[near_bindgen] +/// #[near] /// impl NearRngExample { /// pub fn increment(&mut self) { /// let mut rng = Rng::new(&env::random_seed()); diff --git a/near-sdk/src/json_types/hash.rs b/near-sdk/src/json_types/hash.rs index bb76b93d6..43ef56f44 100644 --- a/near-sdk/src/json_types/hash.rs +++ b/near-sdk/src/json_types/hash.rs @@ -1,12 +1,11 @@ use crate::CryptoHash; -use borsh::{BorshDeserialize, BorshSerialize}; use bs58::decode::Error as B58Error; +use near_sdk_macros::near; use serde::{de, ser, Deserialize}; use std::convert::TryFrom; -#[derive( - Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, BorshDeserialize, BorshSerialize, Default, -)] +#[near(inside_nearsdk)] +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)] pub struct Base58CryptoHash(CryptoHash); impl From for CryptoHash { diff --git a/near-sdk/src/json_types/integers.rs b/near-sdk/src/json_types/integers.rs index 4e1e7aab9..aa1c01c6d 100644 --- a/near-sdk/src/json_types/integers.rs +++ b/near-sdk/src/json_types/integers.rs @@ -3,23 +3,13 @@ //! NOTE: JSON standard can only work with integer up to 53 bits. So we need helper classes for //! 64-bit and 128-bit integers. -use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use serde::{Deserialize, Deserializer, Serialize, Serializer}; macro_rules! impl_str_type { ($iden: ident, $ty: tt) => { - #[derive( - Debug, - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - BorshDeserialize, - BorshSerialize, - Default, - )] + #[near(inside_nearsdk)] + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub struct $iden(pub $ty); impl From<$ty> for $iden { diff --git a/near-sdk/src/json_types/vector.rs b/near-sdk/src/json_types/vector.rs index 0f31b55c6..b69e484ae 100644 --- a/near-sdk/src/json_types/vector.rs +++ b/near-sdk/src/json_types/vector.rs @@ -1,9 +1,17 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use near_sdk_macros::near; +use serde::{Deserialize, Deserializer, Serializer}; /// Helper class to serialize/deserialize `Vec` to base64 string. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] -pub struct Base64VecU8(#[serde(with = "base64_bytes")] pub Vec); + +#[near(inside_nearsdk, serializers=[borsh, json])] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Base64VecU8( + #[serde( + serialize_with = "base64_bytes::serialize", + deserialize_with = "base64_bytes::deserialize" + )] + pub Vec, +); impl From> for Base64VecU8 { fn from(v: Vec) -> Self { @@ -17,21 +25,6 @@ impl From for Vec { } } -#[cfg(feature = "abi")] -impl schemars::JsonSchema for Base64VecU8 { - fn is_referenceable() -> bool { - false - } - - fn schema_name() -> String { - String::schema_name() - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - String::json_schema(gen) - } -} - /// Convenience module to allow anotating a serde structure as base64 bytes. /// /// # Example diff --git a/near-sdk/src/lib.rs b/near-sdk/src/lib.rs index 2a97f93ce..8a219a258 100644 --- a/near-sdk/src/lib.rs +++ b/near-sdk/src/lib.rs @@ -8,7 +8,7 @@ extern crate quickcheck; pub use near_sdk_macros::{ - ext_contract, near_bindgen, BorshStorageKey, EventMetadata, FunctionError, NearSchema, + ext_contract, near, near_bindgen, BorshStorageKey, EventMetadata, FunctionError, NearSchema, PanicOnDefault, }; diff --git a/near-sdk/src/promise.rs b/near-sdk/src/promise.rs index 4fd436ea9..56f03ec33 100644 --- a/near-sdk/src/promise.rs +++ b/near-sdk/src/promise.rs @@ -192,18 +192,17 @@ impl PromiseJoint { /// execution of method `ContractB::b` of `bob_near` account, and the return value of `ContractA::a` /// will be what `ContractB::b` returned. /// ```no_run -/// # use near_sdk::{ext_contract, near_bindgen, Promise, Gas}; -/// # use borsh::{BorshDeserialize, BorshSerialize}; +/// # use near_sdk::{ext_contract, near, Promise, Gas}; /// #[ext_contract] /// pub trait ContractB { /// fn b(&mut self); /// } /// -/// #[near_bindgen] -/// #[derive(Default, BorshDeserialize, BorshSerialize)] +/// #[near(contract_state)] +/// #[derive(Default)] /// struct ContractA {} /// -/// #[near_bindgen] +/// #[near] /// impl ContractA { /// pub fn a(&self) -> Promise { /// contract_b::ext("bob_near".parse().unwrap()).b() @@ -469,18 +468,17 @@ impl Promise { /// /// In the below code `a1` and `a2` functions are equivalent. /// ``` - /// # use near_sdk::{ext_contract, Gas, near_bindgen, Promise}; - /// # use borsh::{BorshDeserialize, BorshSerialize}; + /// # use near_sdk::{ext_contract, Gas, near, Promise}; /// #[ext_contract] /// pub trait ContractB { /// fn b(&mut self); /// } /// - /// #[near_bindgen] - /// #[derive(Default, BorshDeserialize, BorshSerialize)] + /// #[near(contract_state)] + /// #[derive(Default)] /// struct ContractA {} /// - /// #[near_bindgen] + /// #[near] /// impl ContractA { /// pub fn a1(&self) { /// contract_b::ext("bob_near".parse().unwrap()).b().as_return(); @@ -552,7 +550,7 @@ impl schemars::JsonSchema for Promise { /// or `PromiseOrValue::Value` to specify which one should be returned. /// # Example /// ```no_run -/// # use near_sdk::{ext_contract, near_bindgen, Gas, PromiseOrValue}; +/// # use near_sdk::{ext_contract, near, Gas, PromiseOrValue}; /// #[ext_contract] /// pub trait ContractA { /// fn a(&mut self); diff --git a/near-sdk/src/store/free_list/mod.rs b/near-sdk/src/store/free_list/mod.rs index bc6c502d1..0903c49c4 100644 --- a/near-sdk/src/store/free_list/mod.rs +++ b/near-sdk/src/store/free_list/mod.rs @@ -3,18 +3,23 @@ pub use self::iter::{Drain, Iter, IterMut}; use super::{Vector, ERR_INCONSISTENT_STATE}; use crate::{env, IntoStorageKey}; +use near_sdk_macros::{near, NearSchema}; use borsh::{BorshDeserialize, BorshSerialize}; use std::{fmt, mem}; /// Index for value within a bucket. -#[derive(BorshSerialize, BorshDeserialize, Debug, Hash, PartialEq, Eq, Clone, Copy)] +#[near(inside_nearsdk)] +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] pub struct FreeListIndex(pub(crate) u32); /// Unordered container of values. This is similar to [`Vector`] except that values are not /// re-arranged on removal, keeping the indices consistent. When an element is removed, it will /// be replaced with an empty cell which will be populated on the next insertion. +#[derive(NearSchema)] +#[inside_nearsdk] +#[abi(borsh)] pub(crate) struct FreeList where T: BorshSerialize, @@ -51,7 +56,8 @@ where } } -#[derive(BorshDeserialize, BorshSerialize, Debug)] +#[near(inside_nearsdk)] +#[derive(Debug)] enum Slot { /// Represents a filled cell of a value in the collection. Occupied(T), diff --git a/near-sdk/src/store/index_map.rs b/near-sdk/src/store/index_map.rs index 7d1df75c8..63ea9c5b9 100644 --- a/near-sdk/src/store/index_map.rs +++ b/near-sdk/src/store/index_map.rs @@ -1,6 +1,7 @@ use std::fmt; use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use once_cell::unsync::OnceCell; use crate::utils::StableMap; @@ -9,7 +10,7 @@ use crate::{env, CacheEntry, EntryState, IntoStorageKey}; const ERR_ELEMENT_DESERIALIZATION: &str = "Cannot deserialize element"; const ERR_ELEMENT_SERIALIZATION: &str = "Cannot serialize element"; -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub(crate) struct IndexMap where T: BorshSerialize, diff --git a/near-sdk/src/store/lazy/mod.rs b/near-sdk/src/store/lazy/mod.rs index c437a4fbd..87e544d22 100644 --- a/near-sdk/src/store/lazy/mod.rs +++ b/near-sdk/src/store/lazy/mod.rs @@ -9,6 +9,8 @@ mod impls; use borsh::{to_vec, BorshDeserialize, BorshSerialize}; use once_cell::unsync::OnceCell; +use near_sdk_macros::near; + use crate::env; use crate::store::ERR_INCONSISTENT_STATE; use crate::utils::{CacheEntry, EntryState}; @@ -59,7 +61,7 @@ where /// *a = "new string".to_string(); /// assert_eq!(a.get(), "new string"); /// ``` -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct Lazy where T: BorshSerialize, diff --git a/near-sdk/src/store/lazy_option/mod.rs b/near-sdk/src/store/lazy_option/mod.rs index 6971a58db..8591f9e09 100644 --- a/near-sdk/src/store/lazy_option/mod.rs +++ b/near-sdk/src/store/lazy_option/mod.rs @@ -1,6 +1,7 @@ mod impls; use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use once_cell::unsync::OnceCell; use crate::env; @@ -31,7 +32,7 @@ use crate::IntoStorageKey; /// assert_eq!(a.get(), &Some("new new value".to_owned())); /// ``` /// [`Deref`]: std::ops::Deref -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct LazyOption where T: BorshSerialize, diff --git a/near-sdk/src/store/lookup_map/mod.rs b/near-sdk/src/store/lookup_map/mod.rs index 927b2d65a..71996e4eb 100644 --- a/near-sdk/src/store/lookup_map/mod.rs +++ b/near-sdk/src/store/lookup_map/mod.rs @@ -5,6 +5,7 @@ use std::borrow::Borrow; use std::fmt; use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; use once_cell::unsync::OnceCell; use super::ERR_NOT_EXIST; @@ -75,7 +76,8 @@ const ERR_ELEMENT_SERIALIZATION: &str = "Cannot serialize element"; /// ``` /// /// [`with_hasher`]: Self::with_hasher -#[derive(BorshSerialize, BorshDeserialize)] + +#[near(inside_nearsdk)] pub struct LookupMap where K: BorshSerialize + Ord, diff --git a/near-sdk/src/store/lookup_set/mod.rs b/near-sdk/src/store/lookup_set/mod.rs index b2d1ac07e..bfa55ab1f 100644 --- a/near-sdk/src/store/lookup_set/mod.rs +++ b/near-sdk/src/store/lookup_set/mod.rs @@ -2,11 +2,13 @@ mod impls; use crate::store::key::{Identity, ToKey}; use crate::{env, IntoStorageKey}; -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::BorshSerialize; use std::borrow::Borrow; use std::fmt; use std::marker::PhantomData; +use near_sdk_macros::near; + /// A non-iterable implementation of a set that stores its content directly on the storage trie. /// /// This set stores the values under a hash of the set's `prefix` and [`BorshSerialize`] of the @@ -44,7 +46,7 @@ use std::marker::PhantomData; /// ``` /// /// [`with_hasher`]: Self::with_hasher -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] pub struct LookupSet where T: BorshSerialize, diff --git a/near-sdk/src/store/tree_map/iter.rs b/near-sdk/src/store/tree_map/iter.rs index e52c79e3f..05778b82a 100644 --- a/near-sdk/src/store/tree_map/iter.rs +++ b/near-sdk/src/store/tree_map/iter.rs @@ -1,3 +1,4 @@ +use near_sdk_macros::near; use std::ops::Bound; use std::vec::Vec; use std::{borrow::Borrow, iter::FusedIterator}; @@ -998,7 +999,8 @@ impl Find { } } -#[derive(BorshDeserialize, BorshSerialize, Debug, Copy, Clone)] +#[near(inside_nearsdk)] +#[derive(Debug, Copy, Clone)] enum FindUnbounded { /// Find the first element in the given root First, diff --git a/near-sdk/src/store/tree_map/mod.rs b/near-sdk/src/store/tree_map/mod.rs index 013b003cf..b18d67b28 100644 --- a/near-sdk/src/store/tree_map/mod.rs +++ b/near-sdk/src/store/tree_map/mod.rs @@ -14,6 +14,8 @@ use std::borrow::Borrow; use std::fmt; use std::ops::RangeBounds; +use near_sdk_macros::near; + type NodeAndIndex<'a, K> = (FreeListIndex, &'a Node); fn expect(val: Option) -> T { @@ -92,7 +94,7 @@ where } } -#[derive(BorshDeserialize, BorshSerialize)] +#[near(inside_nearsdk)] struct Tree where K: BorshSerialize, @@ -114,7 +116,8 @@ where } } -#[derive(Clone, BorshSerialize, BorshDeserialize, Debug)] +#[near(inside_nearsdk)] +#[derive(Clone, Debug)] struct Node { key: K, // key stored in a node lft: Option, // left link of a node diff --git a/near-sdk/src/store/unordered_map/mod.rs b/near-sdk/src/store/unordered_map/mod.rs index 89165a140..c99852f25 100644 --- a/near-sdk/src/store/unordered_map/mod.rs +++ b/near-sdk/src/store/unordered_map/mod.rs @@ -10,6 +10,8 @@ use std::{fmt, mem}; use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::near; + use crate::store::key::{Sha256, ToKey}; use crate::{env, IntoStorageKey}; @@ -98,7 +100,7 @@ where values: LookupMap, H>, } -#[derive(BorshSerialize, BorshDeserialize)] +#[near(inside_nearsdk)] struct ValueAndIndex { value: V, key_index: FreeListIndex, diff --git a/near-sdk/src/store/vec/mod.rs b/near-sdk/src/store/vec/mod.rs index 34f30d523..bca382e7c 100644 --- a/near-sdk/src/store/vec/mod.rs +++ b/near-sdk/src/store/vec/mod.rs @@ -61,6 +61,7 @@ use std::{ }; use borsh::{BorshDeserialize, BorshSerialize}; +use near_sdk_macros::NearSchema; pub use self::iter::{Drain, Iter, IterMut}; use super::ERR_INCONSISTENT_STATE; @@ -111,6 +112,9 @@ fn expect_consistent_state(val: Option) -> T { /// vec.extend([1, 2, 3].iter().copied()); /// assert!(Iterator::eq(vec.into_iter(), [7, 1, 2, 3].iter())); /// ``` +#[derive(NearSchema)] +#[inside_nearsdk] +#[abi(borsh)] pub struct Vector where T: BorshSerialize, @@ -193,7 +197,7 @@ where self.len == 0 } - /// Create new vector with zero elements. Prefixes storage accesss with the prefix provided. + /// Create new vector with zero elements. Prefixes storage access with the prefix provided. /// /// This prefix can be anything that implements [`IntoStorageKey`]. The prefix is used when /// storing and looking up values in storage to ensure no collisions with other collections. @@ -543,7 +547,7 @@ where #[cfg(test)] mod tests { use arbitrary::{Arbitrary, Unstructured}; - use borsh::{to_vec, BorshDeserialize, BorshSerialize}; + use borsh::{to_vec, BorshDeserialize}; use rand::{Rng, RngCore, SeedableRng}; use super::Vector; @@ -682,8 +686,10 @@ mod tests { // * The storage is reused in the second part of this test, need to flush vec.flush(); - use borsh::{BorshDeserialize, BorshSerialize}; - #[derive(Debug, BorshSerialize, BorshDeserialize)] + use near_sdk_macros::near; + + #[near(inside_nearsdk)] + #[derive(Debug)] struct TestType(u64); let deserialize_only_vec = diff --git a/near-sdk/src/types/error.rs b/near-sdk/src/types/error.rs index 004c2d192..b72be55cd 100644 --- a/near-sdk/src/types/error.rs +++ b/near-sdk/src/types/error.rs @@ -37,14 +37,13 @@ where /// abort without a custom message. /// /// ``` -/// use near_sdk::borsh::{BorshDeserialize, BorshSerialize}; -/// use near_sdk::{Abort, near_bindgen}; +/// use near_sdk::{Abort, near}; /// -/// #[near_bindgen] -/// #[derive(Default, BorshDeserialize, BorshSerialize)] +/// #[near(contract_state)] +/// #[derive(Default)] /// pub struct Contract; /// -/// #[near_bindgen] +/// #[near] /// impl Contract { /// #[handle_result] /// pub fn foo(&self, text: &str) -> Result { diff --git a/near-sdk/src/types/public_key.rs b/near-sdk/src/types/public_key.rs index e504ae329..c66640765 100644 --- a/near-sdk/src/types/public_key.rs +++ b/near-sdk/src/types/public_key.rs @@ -1,11 +1,12 @@ use borsh::{BorshDeserialize, BorshSerialize}; use bs58::decode::Error as B58Error; +use near_sdk_macros::near; use std::{convert::TryFrom, io}; /// PublicKey curve -#[derive(Debug, Clone, Copy, PartialOrd, Ord, Eq, PartialEq, BorshDeserialize, BorshSerialize)] +#[near(inside_nearsdk, serializers=[borsh(use_discriminant = true)])] +#[derive(Debug, Clone, Copy, PartialOrd, Ord, Eq, PartialEq)] #[repr(u8)] -#[borsh(use_discriminant = true)] pub enum CurveType { ED25519 = 0, SECP256K1 = 1, diff --git a/near-sdk/tests/event_tests.rs b/near-sdk/tests/event_tests.rs index 5f1983e7c..202d2b24d 100644 --- a/near-sdk/tests/event_tests.rs +++ b/near-sdk/tests/event_tests.rs @@ -1,7 +1,7 @@ use near_sdk::test_utils::get_logs; -use near_sdk::{near_bindgen, AccountId}; +use near_sdk::{near, AccountId}; -#[near_bindgen(event_json(standard = "test_standard"))] +#[near(event_json(standard = "test_standard"))] pub enum TestEvents<'a, 'b, T> where T: near_sdk::serde::Serialize, @@ -25,7 +25,7 @@ where mod private { use super::*; - #[near_bindgen(event_json(standard = "another_standard"))] + #[near(event_json(standard = "another_standard"))] pub enum AnotherEvent { #[event_version("1.0.0")] Test,