near_kit/contract.rs
1//! Typed contract interfaces.
2//!
3//! This module provides the [`Contract`] trait for creating type-safe contract
4//! clients using the `#[near_kit::contract]` proc macro.
5//!
6//! # Why Typed Contracts?
7//!
8//! Without typed contracts, method names and arguments are stringly-typed:
9//!
10//! ```rust,no_run
11//! # use near_kit::*;
12//! # async fn example(near: &Near) -> Result<(), Error> {
13//! // Typos compile fine but fail at runtime
14//! let count: u64 = near.view("counter.near", "get_counnt").await?; // typo!
15//! # Ok(())
16//! # }
17//! ```
18//!
19//! With typed contracts, the compiler catches errors:
20//!
21//! ```ignore
22//! let counter = near.contract::<Counter>("counter.near");
23//! let count = counter.get_count().await?; // Compile-time checked!
24//! ```
25//!
26//! # Defining a Contract Interface
27//!
28//! Use the `#[near_kit::contract]` macro on a trait:
29//!
30//! ```ignore
31//! use near_kit::*;
32//! use serde::Serialize;
33//!
34//! #[near_kit::contract]
35//! pub trait Counter {
36//! // View method: &self, no #[call] attribute
37//! fn get_count(&self) -> u64;
38//!
39//! // Change method: &mut self + #[call] attribute
40//! #[call]
41//! fn increment(&mut self);
42//!
43//! // Change method with arguments
44//! #[call]
45//! fn add(&mut self, args: AddArgs);
46//!
47//! // Payable method (can receive NEAR deposit)
48//! #[call(payable)]
49//! fn donate(&mut self);
50//! }
51//!
52//! #[derive(Serialize)]
53//! pub struct AddArgs {
54//! pub value: u64,
55//! }
56//! ```
57//!
58//! # Using a Typed Contract
59//!
60//! ```ignore
61//! async fn example(near: &Near) -> Result<(), Error> {
62//! let counter = near.contract::<Counter>("counter.testnet");
63//!
64//! // View calls
65//! let count = counter.get_count().await?;
66//!
67//! // Change calls
68//! counter.increment().await?;
69//! counter.add(AddArgs { value: 5 }).await?;
70//!
71//! // Payable calls with deposit
72//! counter.donate().deposit(NearToken::near(1)).await?;
73//!
74//! // Override gas
75//! counter.add(AddArgs { value: 10 }).gas(Gas::tgas(50)).await?;
76//!
77//! Ok(())
78//! }
79//! ```
80//!
81//! # Serialization Formats
82//!
83//! By default, arguments are serialized as JSON. For Borsh serialization:
84//!
85//! ```ignore
86//! #[near_kit::contract(borsh)]
87//! pub trait MyContract {
88//! fn my_method(&self, args: MyArgs) -> u64;
89//! }
90//! ```
91
92use crate::client::Near;
93use crate::types::AccountId;
94
95/// Marker trait for typed contract interfaces.
96///
97/// This trait is automatically implemented by the `#[near_kit::contract]` macro
98/// for each contract trait you define. It provides the associated `Client` type
99/// that is used by [`Near::contract`](crate::Near::contract).
100///
101/// # Example
102///
103/// The macro generates an implementation like this:
104///
105/// ```ignore
106/// impl Contract for dyn MyContract {
107/// type Client<'a> = MyContractClient<'a>;
108/// }
109/// ```
110pub trait Contract {
111 /// The generated client type for this contract interface.
112 type Client<'a>: ContractClient<'a>;
113}
114
115/// Trait for contract client constructors.
116///
117/// This trait is implemented by the generated client structs to enable
118/// construction via [`Near::contract`](crate::Near::contract).
119pub trait ContractClient<'a>: Sized {
120 /// Create a new contract client.
121 fn new(near: &'a Near, contract_id: AccountId) -> Self;
122}