near-sdk-rs

repository·master·Indexed 19 days ago

https://github.com/near/near-sdk-rs

The official Rust SDK for developing smart contracts on the NEAR blockchain. It provides macros, environment access, and cross-contract communication tools. The SDK supports building contracts into WebAssembly (WASM) using cargo-near, with options for standard non-reproducible builds and reproducible builds. It includes support for global contracts (NEP-591) and provides a Contract Builder Docker environment for reproducible binaries.

Tokens
52.3K
Snippets
191
Records
226
Agent score
67%

What's inside near-sdk-rs

  1. Overview of near-sdk

    master

    The near-sdk is a Rust library used for writing smart contracts for the NEAR blockchain. It provides macros and utilities to handle contract state, blockchain environment interactions, and cross-contract calls.

    Key Specifications:

    • Minimum Supported Rust Version (MSRV): 1.93.0
    • Previous Name: near-bindgen.
  2. Implement NEAR contract standards in Rust

    master

    The near-contract-standards crate provides standardized interfaces and implementations for common NEAR Protocol contract patterns. Use this library to ensure your Rust contracts adhere to official standards for:

    • Upgradability: Standardized patterns for upgrading contract code.
    • Fungible Token (NEP-141): Implementation of the NEAR Fungible Token standard. For a concrete implementation guide, refer to the fungible-token example in the repository.
  3. What is near-sdk-env and when to use it

    master

    near-sdk-env is a low-level abstraction over near-sys host functions. It provides a unified API that works both on-chain (inside a WASM contract) and off-chain (in tests, doctests, or off-chain tools).

    • On-chain (wasm32): Functions are routed through NEAR VM host calls.
    • Off-chain (non-wasm32): Functions fallback to Rust implementations (e.g., sha2, sha3, ripemd).

    Important Limitation: Not all functions available in the high-level near-sdk are available in near-sdk-env. Functions that require direct interaction with the blockchain state—such as random_seed_array() or block_height()—cannot be reliably mimicked off-chain and are therefore excluded from this low-level environment abstraction.

  4. Use near-sdk-core for off-chain applications

    master

    The near-sdk-core crate provides foundational NEAR types required for off-chain usage. Use these types when building tools that interact with the NEAR blockchain but do not run as smart contracts on-chain.

    Key types provided include:

    • PublicKey
    • AccountId
    • U128
    • Base64VecU8
  5. Implement versioned state in NEAR contracts

    master
    You can implement contract versioning by defining your contract state as an enum. This approach is useful for upgradable contracts because it allows you to handle different state formats within a single type, avoiding the need to write manual migration functions or risk errors when deserializing old state formats during an upgrade.
  6. How hashing backends are selected

    master

    The crate automatically selects the hashing backend based on the compilation target:

    1. On-chain (--cfg near): When built using cargo-near build, the crate routes hashing through NEAR host functions via near-sdk-env.
    2. Off-chain/Non-NEAR (cfg(not(near))): When built for other targets (e.g., wasm32-unknown-unknown without --cfg near), it uses pure-Rust sha3 hashing. This allows the code to run in non-NEAR WASM runtimes like TEE-hosted environments without requiring NEAR host function imports.
  7. Initialize contract state with #[init]

    master

    Use the #[init] attribute on a method to define a specific initialization routine. The #[init] macro ensures that the method can only be called if the contract has not been initialized yet; it will panic if called a second time.

    Note: Even with an #[init] method, your struct must still implement Default. To prevent accidental usage of the default state, you can implement Default to panic or use the #[derive(PanicOnDefault)] macro.

    #[near]
    impl StatusMessage {
        #[init]
        pub fn new(user: String, status: String) -> Self {
            let mut res = Self::default();
            res.records.insert(user, status);
            res
        }
    }
    
    // To prevent default initialization:
    #[near(contract_state)]
    #[derive(PanicOnDefault)]
    pub struct StatusMessage {
        records: HashMap<String, String>,
    }
  8. Use the yield promise API in MPC contracts

    master

    The MPC Contract example demonstrates how to use the yield promise API to handle asynchronous signing workflows.

    1. sign: Initiates a request for signing. When called via as-transaction, the transaction enters a waiting state.
    2. get_requests: A read-only function used to retrieve pending requests and their associated data_id.
    3. sign_respond: Resumes a pending transaction by providing the required data_id and the resulting signature.

    Note: The sign_respond call must be completed within the timeout period (e.g., 200 blocks) to successfully resume the original sign transaction.

  9. Use Global Contracts to reduce deployment costs

    master

    Global contracts allow you to share contract code globally across the NEAR network. Instead of deploying the same bytecode multiple times, you can deploy it once as a global contract and have other contracts reference it. This reduces storage costs and enables efficient code reuse.

    Core Workflow:

    1. Deploy Global Contract: A contract deploys bytecode as a global contract, making it available network-wide.
    2. Reference by Hash: Other contracts can reference the global contract using its unique code hash.
    3. Reference by Account: Contracts can reference a global contract by the account ID of the deployer.

    Common Use Cases (NEP-591):

    • Multisig Contracts: Deploy the logic once and use it for many different wallets without paying full deployment costs for each.
    • Smart Contract Wallets: Efficient user onboarding using chain signatures.
    • Business Onboarding: Cost-effective deployment of user accounts for companies.
    • DeFi Templates: Sharing common contract patterns across different protocols.
  10. Important constraints for NFT JSON calls

    master

    When interacting with the NFT contract via JSON calls, adhere to these technical constraints:

    • Balance Values: The maximum balance is limited by U128 ($2^{128} - 1$).
    • Numeric Formatting: Pass U128 or U64 values as base-10 strings (e.g., use "100" instead of a raw integer).
    • Escrow/Approvals: The core NFT standard does not include escrow/approval functionality. Instead, use nft_transfer_call for superior handling. If you require approval management, refer to the approval management standard.
  11. Perform asynchronous cross-contract calls

    master

    The near-sdk allows for asynchronous cross-contract calls via the env module, enabling parallel execution and subsequent aggregation.

    Key env methods for promises:

    • promise_create: Schedules execution of a function on another contract.
    • promise_then: Attaches a callback to the current contract once the promise executes.
    • promise_and: A combinator that waits for multiple promises before executing a callback.
    • promise_return: Treats the result of a promise as the result of the current function.
  12. Implement NEAR contract standards

    master

    The near-contract-standards crate provides interfaces and implementations for official NEAR standards. Use these to ensure your contract is compatible with the ecosystem:

    • Upgradability: Standard patterns for upgrading contract code.
    • Fungible Token (NEP-141): Implementation for fungible tokens.
    • Non-Fungible Token (NEP-171): Implementation for non-fungible tokens.