The Contract Class
Your contract's logic and state (storage) is defined by the main class, in which:
- The attributes define the contract's state
 - The initialization methods define how to initialize the contract's state
 - The public methods act as the contract's interface with the rest of the network
 
Defining the Contract
The contract is just another class, with its own attributes and methods. To differentiate it from other
internal classes simply decorate it using the NEAR Bindgen decorator/macro.
- 🌐 JavaScript
 - 🦀 Rust
 
loading...
loading...
Under the hood, the NEAR Bindgen decorator/macro traverses the class, generating the necessary code to:
- Transform the code into a valid NEAR contract.
 - Expose public methods, so they can be called externally.
 - Serialize objects for internal storage and communication with external actors.
 
The State
Each account has its own state (storage), which only they can modify but anyone can see.
The state is defined and modified through the main class' attributes.
Contracts pay for their storage by locking part of their balance. Currently it costs ~1 Ⓝ to store 100kb
The contract actually uses a key-value storage to persist values. This however is abstracted from you
by the SDK through serialization.
When defining attributes, always prefer SDK collections over native ones, since they are optimized for serialization.
Initializing the State
There are two ways to initialize the account's state, and they can co-exist:
- An initialization method that receives the attributes needed for the state
 - A default state, which will be used until 
initis invoked, or a method writes into the state 
Initialization Method
To define an initialization method simply decorate it with the initialization macro.
The method will now be able to define the initial state's values, raising an error if invoked while the state is already initialized.
- 🌐 JavaScript
 - 🦀 Rust
 - 🚀 AssemblyScript
 
loading...
To make the initialization mandatory use @NearBindgen({requireInit: true})
In JavaScript you must always define a default state
loading...
To make the initialization mandatory use #[derive(PanicOnDefault)] in the contract's structure
  // Public - init function, define the beneficiary of donations
  export function init(beneficiary: string): void {
    assert(context.predecessor == context.contractName, "Method new is private");
    set_beneficiary(beneficiary);
  }
  🚀 - AssemblyScript has no #[init] macro, and any method can be called multiple times. Limit this by adding a flag:
  const initialized: bool = storage.getPrimitive<bool>('init', false)
  assert(!initialized, "Already initialized")
  storage.set<bool>('init', true)
Default State
Contracts can define a default state to use if no initialize method is called. This is, if any method is invoked
before an init happens, the contract will use the default values.
Once any method writes into the state, the state will be considered initialized.
- 🌐 JavaScript
 - 🦀 Rust
 
loading...
🌐 In JavaScript, the default state is defined by the initialization parameters in the class definition.
In Javascript you must always assign values to all the class' parameters. This ensures they get correctly deserialized to their intended type.
loading...
Interface
All the public methods are exposed to the network as the contract's interface.
- 🌐 JavaScript
 - 🦀 Rust
 - 🚀 AssemblyScript
 
@NearBindgen({})
class Contract {
  @initialize({ ... })
  init({ ... }) { /* public `init` method */ }
  @view({})
  get_message({ ...  }) { /* public `view` method */ }
  @call({})
  add_message({ ... }) { /* public `call` method */ }
  private internal_search( ... ) { /* private internal method */ }
  @call({privateFunction: true})
  set_owner({ ... }) { /* public, panics when caller is not the contract's account */ }
}
#[near_bindgen]
impl Contract {
  #[init]
  pub fn init( ... ) -> Self { /* public `init` method */ }
  pub fn get_message(&self, ... ) { /* public `view` method */ }
  pub fn add_message(&mut self, ... ) { /* public `call` method */ }
  fn internal_search(&self, ... ) { /* private internal method */ }
  #[private]
  pub fn set_owner(&mut self, ... ) { /* public, panics when caller is not the contract's account */ }
}
export function get_message({ ...  }) { ... }
export function set_owner({ ... }) { ... }
export function add_message({ ... }) { ... }
private function internal_search( ... ) { ... }
Public Methods
Public methods can be categorized in three types: init methods, view methods, and call methods.
- Init Methods: They define how to initialize the state of the contract.
 - View Methods: Do not mutate the state nor call other contracts. They can be called for free by everyone, without needing a NEAR account.
 - Call Methods: They can mutate the state and perform actions such as calling other contracts.
 
By default view methods have 200TGas to execute, to increase this you can simple invoke them
as call methods
By default init methods are public, make sure to decorate them as private, or batch call the initialization on deploy
Private Methods
Sometimes you will want some methods to remain public, but only be callable by the contract's account. Such is the case for example of cross-contract callbacks.
For this, you can use the private macro/decorator.
- 🌐 JavaScript
 - 🦀 Rust
 
@call({privateFunction: true})
callback( ... ){
  // this method can only be called by the contract's account
}
#[private]
pub fn callback(&mut self, ... ){
  // this method can only be called by the contract's account
}
Payable Methods
By default all methods panic if a user attaches money while calling them. To enable a method to receive money use the payable decorator.
- 🌐 JavaScript
 - 🦀 Rust
 
@call({payableFunction: true})
deposit_and_stake( ... ){
  // this method can receive money from the user
}
#[payable]
pub fn deposit_and_stake(&mut self, ... ){
  // this method can receive money from the user
}
Input & Return Types
The contract can receive and return any native type, including complex structures. However,
since contracts communicate through their interface using JSON:
- Always prefer 
native typesoverSDK Collectionsin the input & return types. - Replace 
u64/u128forstrings(U64/U128in the Rust SDK).