Skip to main content

Storage & Data Structures

Each contract has its own storage, which only they can modify but anyone can see.

Contracts store data as key-value pairs, but our SDK enables to use common data types and structures.

Smart contracts pay for their storage by locking a part of their balance (~1 โ“ƒ per 100kb).


Attributes and Constantsโ€‹

You can store constants and define contract's attributes.

storage-js/src/index.ts
loading...

Data Structuresโ€‹

Our SDK exposes a series of data structures to simplify handling and storing data.

The most common ones are Vectors, Sets, Maps and Trees.

caution

Use unique IDs when initializing structures, otherwise they will point to the same key-value references.


Vectorโ€‹

Implements a vector/array which persists in the contract's storage. Please refer to the Rust and AS SDK's for a full reference on their interfaces.

storage-js/src/index.ts
loading...

Mapโ€‹

Implements a map/dictionary which persists in the contract's storage. Please refer to the Rust and AS SDK's for a full reference on their interfaces.

storage-js/src/index.ts
loading...
Nesting of Objects - Temporary Solution

In the JS SDK, you can store and retrieve elements from a nested map or object, but first you need to construct or deconstruct the structure from state. This is a temporary solution until the improvements have been implemented to the SDK. Here is an example of how to do this:

import { NearBindgen, call, view, near, UnorderedMap } from "near-sdk-js";

@NearBindgen({})
class StatusMessage {
records: UnorderedMap;
constructor() {
this.records = new UnorderedMap("a");
}

@call({})
set_status({ message, prefix }: { message: string; prefix: string }) {
let account_id = near.signerAccountId();

const inner: any = this.records.get("b" + prefix);
const inner_map: UnorderedMap = inner
? UnorderedMap.deserialize(inner)
: new UnorderedMap("b" + prefix);

inner_map.set(account_id, message);

this.records.set("b" + prefix, inner_map);
}

@view({})
get_status({ account_id, prefix }: { account_id: string; prefix: string }) {
const inner: any = this.records.get("b" + prefix);
const inner_map: UnorderedMap = inner
? UnorderedMap.deserialize(inner)
: new UnorderedMap("b" + prefix);
return inner_map.get(account_id);
}
}

Setโ€‹

Implements a set which persists in the contract's storage. Please refer to the Rust and AS SDK's for a full reference on their interfaces.

storage-js/src/index.ts
loading...

Treeโ€‹

An ordered equivalent of Map. The underlying implementation is based on an AVL. You should use this structure when you need to: have a consistent order, or access the min/max keys.

storage-rs/contract/src/tree.rs
loading...

Storage Costโ€‹

Your contract needs to lock a portion of their balance proportional to the amount of data they stored in the blockchain. This means that:

  • If more data is added and the storage increases โ†‘, then your contract's balance decreases โ†“.
  • If data is deleted and the storage decreases โ†“, then your contract's balance increases โ†‘.

Currently, it cost approximately 1 โ“ƒ to store 100kb of data.

caution

An error will raise if your contract tries to increase its state while not having NEAR to cover for storage.

danger

Be mindful of potential small deposit attacks