diff --git a/docs/chain-abstraction/omnibridge/how-it-works.md b/docs/chain-abstraction/omnibridge/how-it-works.md index a0e37d0d345..b2f1cf02220 100644 --- a/docs/chain-abstraction/omnibridge/how-it-works.md +++ b/docs/chain-abstraction/omnibridge/how-it-works.md @@ -23,7 +23,7 @@ Before exploring how Chain Signatures solves these issues, it's important to und When a token transfer happens on NEAR using `ft_transfer_call`, the token contract first transfers the tokens and then automatically calls the specified `ft_on_transfer` method on the receiver contract. While these operations happen in sequence within the same transaction, the receiver contract has the ability to reject the transfer, causing the tokens to be refunded. This atomic behavior ensures the integrity and safety of bridge operations by preventing partial execution states. -For more information see [Fungible Tokens](../../primitives/ft.md). +For more information see [Fungible Tokens](../../primitives/ft/ft.md). ## Enter Chain Signatures diff --git a/docs/primitives/dao.md b/docs/primitives/dao.md index adf4c66f31d..aa699aa9d6d 100644 --- a/docs/primitives/dao.md +++ b/docs/primitives/dao.md @@ -2,7 +2,6 @@ id: dao title: Decentralized Autonomous Organizations sidebar_label: Autonomous Organizations (DAO) -hide_table_of_contents: false description: "Learn about Decentralized Autonomous Organizations (DAOs) on NEAR - self-organized groups that coordinate membership, decision-making, and funding through smart contract voting." --- @@ -18,7 +17,7 @@ Decentralized Autonomous Organizations (DAOs) are self-organized groups that for ![dao](/assets/docs/primitives/dao.png) -In contrast with [FT](ft.md) and [NFT](nft.md), DAO contract's are not standardized. Because of this, on this page we will use as +In contrast with [FT](./ft/ft.md) and [NFT](./nft/nft.md), DAO contract's are not standardized. Because of this, on this page we will use as reference the [Astra dao](https://dev.near.org/astraplusplus.ndctools.near/widget/home?page=daos) [contract](https://github.com/near-daos/sputnik-dao-contract). The main concepts covered here should easily generalizable to other DAO implementations. @@ -176,7 +175,7 @@ Deploying by **hash** creates an immutable contract that never changes. Deployin ### Voting policy Currently, DAOs support two different types of [voting policies](https://github.com/near-daos/sputnik-dao-contract#voting-policy): `TokenWeight`, and `RoleWeight`. -When the vote policy is `TokenWeight`, the council votes using [tokens](ft.md). The weigh of a vote is the proportion of tokens used for voting over the token's total supply. +When the vote policy is `TokenWeight`, the council votes using [tokens](./ft/ft.md). The weigh of a vote is the proportion of tokens used for voting over the token's total supply. When the vote policy is `RoleWeight(role)`, the vote weigh is computed as "one over the total number of people with the role". diff --git a/docs/primitives/dex.md b/docs/primitives/dex.md index 9cfbc742f90..207b92efeb6 100644 --- a/docs/primitives/dex.md +++ b/docs/primitives/dex.md @@ -1,7 +1,6 @@ --- id: dex title: Decentralized Exchanges (DEX) -hide_table_of_contents: false description: "Learn how to interact with decentralized exchanges on NEAR Protocol, including token swapping, liquidity pools, and integration with Ref Finance DEX." --- diff --git a/docs/primitives/didnear.md b/docs/primitives/didnear.md index f45d43de344..7e6ef8fd402 100644 --- a/docs/primitives/didnear.md +++ b/docs/primitives/didnear.md @@ -1,7 +1,6 @@ --- id: did title: Decentralized Identifiers (DIDs) -hide_table_of_contents: false description: "Learn about W3C-compliant identity resolution on NEAR." --- diff --git a/docs/primitives/ft.md b/docs/primitives/ft/ft.md similarity index 84% rename from docs/primitives/ft.md rename to docs/primitives/ft/ft.md index 45b414ab859..4ba22d2ea30 100644 --- a/docs/primitives/ft.md +++ b/docs/primitives/ft/ft.md @@ -1,8 +1,7 @@ --- id: ft -title: Fungible Tokens (FT) -hide_table_of_contents: false -description: "Learn about NEAR fungible tokens (FT) following NEP-141 and NEP-148 standards - create, transfer, and integrate FT contracts with comprehensive examples and tools." +title: Using FTs +description: "Learn how to create, transfer, and integrate FT in your dApp" --- import {FeatureList, Column, Feature} from "@site/src/components/featurelist" @@ -15,36 +14,24 @@ import { TryOutOnLantstool } from "@site/src/components/lantstool/TryOutOnLantst import CreateTokenForm from "@site/src/components/tools/FungibleToken/CreateTokenForm"; - -Besides the native NEAR token, NEAR accounts have access to a [multitude of tokens](https://guide.rhea.finance/developers-1/cli-trading#query-whitelisted-tokens) to use throughout the ecosystem. Moreover, it is even possible for users to create their own fungible tokens. - -In contrast with the NEAR native token, fungible token (FT) are **not stored** in the user's account. In fact, each FT lives in **their own contract** which is in charge of doing **bookkeeping**. This is, the contract keeps track of how many tokens each user has, and handles transfers internally. - -![FT](/assets/docs/primitives/ft.png) - -In order for a contract to be considered a FT-contract it has to follow the [**NEP-141 and NEP-148 standards**](https://github.com/near/NEPs/tree/master/neps/nep-0141.md). The **NEP-141** & **NEP-148** standards explain the **minimum interface** required to be implemented, as well as the expected functionality. +Wanting to use Fungible Tokens (FT) in your dApp? Here you will find all the information you need to get started creating your own tokens, registering users +, querying balances, transferring tokens, and integrating them into your smart contracts. --- ## Creating a New Token -The simplest way to create a new Fungible Token is by using a factory contract, to which you only need to provide the token metadata, and they will automatically deploy and initialize a [canonical FT contract](https://github.com/near-examples/FT). +The simplest way to create a new Fungible Token is by interacting with a factory contract, to which you only need to provide the token metadata, and they will automatically deploy and initialize a [canonical FT contract](https://github.com/near-examples/FT). -
- - 1. Using the Token Factory Tool - -We have created a simple UI to interact with the existing `tkn.primitives.testnet` factory contract +Here you can make a call to the `token.primitives.testnet` by filling out the form below: -
-
- 2. Interacting with a pre-deployed Token Factory smart contract + Manual Interaction -Here is how to directly interact with the factory contract through your application: +Here is how to directly interact with the factory contract through your application: @@ -72,9 +59,9 @@ Here is how to directly interact with the factory contract through your applicat await wallet.callMethod({ method: 'create_token', args, - contractId: 'tkn.primitives.near', + contractId: 'token.primitives.near', gas: 300000000000000, - deposit: '2234830000000000000000000', + deposit: '2234830000000000000000', }); ``` @@ -84,7 +71,7 @@ Here is how to directly interact with the factory contract through your applicat ```bash - near call tkn.primitives.near create_token '{"args":{"owner_id": "bob.near","total_supply": "1000000000","metadata":{"spec": "ft-1.0.0","name": "Test Token","symbol": "TTTEST","icon": "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7","decimals": 18}},"account_id": "bob.near"}' --gas 300000000000000 --depositYocto 2234830000000000000000000 --accountId bob.near + near call token.primitives.near create_token '{"args":{"owner_id": "bob.near","total_supply": "1000000000","metadata":{"spec": "ft-1.0.0","name": "Test Token","symbol": "TTTEST","icon": "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7","decimals": 18}},"account_id": "bob.near"}' --gas 300000000000000 --depositYocto 2234830000000000000000000 --accountId bob.near ``` }> @@ -92,7 +79,7 @@ Here is how to directly interact with the factory contract through your applicat -The FT you create will live in the account `.tkn.primitives.near` (e.g. `test.tkn.primitives.near`). +The FT you create will live in the account `.token.primitives.near` (e.g. `test.token.primitives.near`).
@@ -138,7 +125,7 @@ To initialize a FT contract you will need to deploy it and then call the `new` m ### Global Contracts -You can deploy a new Fungible Token using our global FT contract - a pre-deployed [standard FT contract](https://github.com/near-examples/FT) that you can reuse. [Global contracts](../smart-contracts/global-contracts.md) are deployed once and can be reused by any account without incurring high storage costs. +You can deploy a new Fungible Token using our global FT contract - a pre-deployed [standard FT contract](https://github.com/near-examples/FT) that you can reuse. [Global contracts](../../smart-contracts/global-contracts.md) are deployed once and can be reused by any account without incurring high storage costs. @@ -426,7 +413,7 @@ To send FT to another account you will use the `ft_transfer` method, indicating ## Attaching FTs to a Call Natively, only NEAR tokens (Ⓝ) can be attached to a function calls. However, the FT standard enables to attach fungible tokens in a call by using the FT-contract as intermediary. This means that, instead of you attaching tokens directly to the call, you ask the FT-contract to do both a transfer and a function call in your name. -Let's assume that you need to deposit FTs on Ref Finance. +Let's assume that you need to deposit FTs on [Ref Finance](https://rhea.finance/). @@ -509,15 +496,15 @@ Let's assume that you need to deposit FTs on Ref Finance. How it works: -1. You call ft_transfer_call in the FT contract passing: the receiver, a message, and the amount. +1. You call `ft_transfer_call` in the FT contract passing: the receiver, a message, and the amount. 2. The FT contract transfers the amount to the receiver. -3. The FT contract calls receiver.ft_on_transfer(sender, msg, amount) -4. The FT contract handles errors in the ft_resolve_transfer callback. +3. The FT contract calls `receiver.ft_on_transfer(sender, msg, amount)` +4. The FT contract handles errors in the `ft_resolve_transfer` callback. 5. The FT contract returns you how much of the attached amount was actually used. --- -## Handling Deposits (Contract Only) +## Handling Deposits If you want your contract to handle deposit in FTs you have to implement the `ft_on_transfer` method. When executed, such method will know: @@ -575,7 +562,8 @@ impl FungibleTokenReceiver for Contract { ## Additional Resources -1. [NEP-141 and NEP-148 standards](https://github.com/near/NEPs/tree/master/neps/nep-0141.md) -2. [FT Event Standards](https://github.com/near/NEPs/blob/master/neps/nep-0300.md) -3. [FT reference implementation](https://github.com/near-examples/FT) -4. [Fungible Tokens 101](../tutorials/fts/0-intro.md) - a set of tutorials that cover how to create a FT contract using Rust. \ No newline at end of file +1. [NEP-141 standard](https://github.com/near/NEPs/tree/master/neps/nep-0141.md) +2. [NEP-148 standard](https://github.com/near/NEPs/tree/master/neps/nep-0148.md) +3. [FT Event Standards](https://github.com/near/NEPs/blob/master/neps/nep-0300.md) +4. [FT reference implementation](https://github.com/near-examples/FT) +5. [Fungible Tokens 101](../../tutorials/fts/0-intro.md) - a set of tutorials that cover how to create a FT contract using Rust. \ No newline at end of file diff --git a/docs/primitives/ft/standard.md b/docs/primitives/ft/standard.md new file mode 100644 index 00000000000..203b348c7cd --- /dev/null +++ b/docs/primitives/ft/standard.md @@ -0,0 +1,186 @@ +--- +id: standard +title: The Standard +description: "Learn how Fungible Tokens (FT) are defined on NEAR" +--- + +Besides the native NEAR token, users have access to a multitude of tokens created by institutions and other users known as fungible tokens. + +In contrast with the native token, fungible token (FT) are **not stored** in the user's account, but rather in a smart contract. Such contract is in charge of doing **bookkeeping**, i.e. to track how many tokens each user has, and to handle transfers internally. + +![FT](/assets/docs/primitives/ft.png) + +In order for a contract to be considered a FT contract it has to follow the [**NEP-141**](https://github.com/near/NEPs/tree/master/neps/nep-0141.md) and [**NEP-148 standards**](https://github.com/near/NEPs/tree/master/neps/nep-0148.md)which define the **minimum interface** required to be implemented, as well as the expected functionality. + +--- + +## NEP-141 (Fungible Token Interface) + +[NEP-141](https://github.com/near/NEPs/tree/master/neps/nep-0141.md) is the blueprint for all fungible tokens (e.g. stablecoins, governance tokens, etc.) on NEAR. + +It defines a **common set of rules** and **functions** that the contract MUST implement to be considered a fungible token contract. + +:::tip + +Notice that the NEP-141 defines the **interface** and **expected behavior** of a fungible token contract, but it does not dictate how the internal logic should be implemented + +Different FT contracts can have different internal implementations while still adhering to the NEP-141 standard + +::: + +
+ +### Interface + +#### `ft_total_supply` (*read-only*) + +Returns the total supply of the token + +```ts +ft_total_supply(): string +``` + +
+ +#### `ft_balance_of` (*read-only*) + +Returns the balance of a given account + +```ts +ft_balance_of(account_id: string): string +``` + +
+ +#### `ft_transfer` + +Transfers `amount` of tokens from the account calling the function to a `receiver_id`, optionally the function can include a `memo` field to provide additional information to the contract + +> *Requirement: The caller must attach [exactly 1 yoctoNEAR](../../smart-contracts/security/one_yocto.md) to the call* + +```ts +ft_transfer(receiver_id: string, amount: string, memo: string?): void +``` + +
+ +#### `ft_transfer_call` + +The function transfers `amount` of tokens to the `receiver_id` **and calls the method `ft_on_transfer(sender_id, amount, msg)`** on `receiver_id`. + +Optionally the function can include a `memo` for the FT contract, and a `msg` field to which will be sent to the receiver contract. + +> πŸ“– This function is useful to transfer tokens to a contract and trigger some action on the receiver side in a single transaction, thus acting as **attaching fungible tokens to a function call**. + +> *Requirement: The caller must attach [exactly 1 yoctoNEAR](../../smart-contracts/security/one_yocto.md) to the call* + +```ts +ft_transfer_call(receiver_id: string, amount: string, memo: string?, msg: string): void +``` + +
+ + ft_on_transfer + + Smart contracts expecting to **receive** Fungible Tokens **must** implement this method. + + The method **must** return the amount of tokens that were **NOT used** by the receiver, so that the **sender can be refunded**. + + ```ts + ft_on_transfer(sender_id: string, amount: string, msg: string): string + ``` + + ⚠️ Note that this method does not need to be implemented by the FT contract itself, but rather by any contract that expects to receive fungible tokens + +
+ +
+ +#### `ft_resolve_transfer` + +This method is used as a [callback](../../smart-contracts/anatomy/crosscontract.md#callback-function) to resolve the `ft_transfer_call` transaction, handling refunds if necessary. + +```js +ft_resolve_transfer(sender_id: string, receiver_id: string, amount: string): string +``` + +--- + +## NEP-145 (Storage Management) + +On NEAR, accounts need to pay for the storage they use on the network. As more users hold tokens on a fungible token contract, more information needs to be stored, and thus the contract needs to reserve more storage. + +[NEP-145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) is a standard that defines a common interface for registering users, allowing FT contracts to **charge users for the storage they use**. + +:::tip + +While not mandatory, it is highly recommended for FT contracts to implement the NEP-145 standard to avoid running out of storage + +::: + +
+ +### Interface + +#### `storage_balance_bounds` (*read-only*) +Returns the minimum and maximum storage balance required for an account to be registered with the contract + +```ts +storage_balance_bounds(): { min: string, max?: string} | null +``` + +#### `storage_balance_of` (*read-only*) +Returns the storage balance of a given account, or `null` if the account is not registered + +```ts +storage_balance_of(account_id: string): { total: string, available: string } | null +``` + +#### `storage_unregister` +Removes all information from an account from the contract, returning the storage deposit to the user. The function can only be called by the user themselves. + +```ts +storage_unregister(force?: boolean): boolean +``` + +#### `storage_deposit` +Registers an account with the contract, reserving enough storage to keep track of the user's balance. The function can be called by the user themselves **or by a third party** on behalf of the user. + +```ts +storage_deposit(account_id?: string, registration_only?: boolean): { total: string, available: string } +``` + +#### `storage_withdraw` +Unregisters an account from the contract, returning the storage deposit to the user. The function can only be called by the user themselves. + +```ts +storage_withdraw(amount: string): { total: string, available: string } +``` + + + +--- + +## NEP-148 (Token Metadata) + +[NEP-148](https://github.com/near/NEPs/tree/master/neps/nep-0141.md) is an extension to the NEP-141 standard that defines the fungible tokens **metadata**. + +Metadata provides **key information** about the token, such as its **name, symbol, and decimal precision**, particularly, the following fields MUST be included in the token's metadata: + +- `spec`: a string. Should be `ft-1.0.0` to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the [Fungible Token Core][FT Core] specs +- `name`: the human-readable name of the token +- `symbol`: the abbreviation, like wETH or AMPL +- `decimals`: used in frontends to show the proper significant digits of a token + +The metadata is useful for wallets and other user interfaces to display the token correctly, for example if a token is defined as: + +```json +{ + "spec": "ft-1.0.0", + "name": "My Awesome Token", + "symbol": "MAT", + "decimals": 4 +} +``` + +A balance of `123456` units of such token should be displayed in a user interface as `12.3456 MAT`. \ No newline at end of file diff --git a/docs/primitives/linkdrop.md b/docs/primitives/linkdrop/linkdrop.md similarity index 94% rename from docs/primitives/linkdrop.md rename to docs/primitives/linkdrop/linkdrop.md index 57114a491c8..867cc3b5439 100644 --- a/docs/primitives/linkdrop.md +++ b/docs/primitives/linkdrop/linkdrop.md @@ -1,7 +1,6 @@ --- id: linkdrop -title: Linkdrops -hide_table_of_contents: false +title: Using Linkdrops description: "Learn about linkdrops following NEP-452 standard - distribute assets and onboard users to Web3 apps through simple web links using access keys and the Keypom platform." --- import {FeatureList, Column, Feature} from "@site/src/components/featurelist" @@ -11,13 +10,7 @@ import { Github } from "@site/src/components/UI/Codetabs" import { LantstoolLabel } from "@site/src/components/lantstool/LantstoolLabel/LantstoolLabel"; import { TryOutOnLantstool } from "@site/src/components/lantstool/TryOutOnLantstool"; -Linkdrops allow users to distribute assets and onboard people to Web3 apps through a simple web link. - -![Linkdrop](/assets/docs/primitives/linkdrop.png) - -They work by storing assets and linking [AccessKeys](../protocol/access-keys.md) to them. The `AccessKeys` are then distributed to users in the form of web links. These links take users to a website that automatically uses the keys to call the `claim` method in the `linkdrop` contract. - -In order for a contract to be considered a Linkdrop-contract it has to follow the [**NEP-452 standard**](https://github.com/near/NEPs/blob/master/neps/nep-0452.md). The **NEP-452** explains the **minimum interface** required to be implemented, as well as the expected functionality. +Wanting to use Linkdrops in your dApp? Here you will find all the information you need to get started. :::tip diff --git a/docs/primitives/linkdrop/standard.md b/docs/primitives/linkdrop/standard.md new file mode 100644 index 00000000000..eccc07325de --- /dev/null +++ b/docs/primitives/linkdrop/standard.md @@ -0,0 +1,83 @@ +--- +id: standard +title: The Standard +description: "Learn how Linkdrops are defined on NEAR" +--- + +Linkdrops allow users to distribute assets and onboard people to Web3 apps through a simple web link. + +![Linkdrop](/assets/docs/primitives/linkdrop.png) + +They work by storing assets and linking [AccessKeys](../../protocol/access-keys.md) to them. The `AccessKeys` are then distributed to users in the form of web links. These links take users to a website that automatically uses the keys to call the `claim` method in the `linkdrop` contract. + +In order for a contract to be considered a Linkdrop-contract it has to follow the [**NEP-452 standard**](https://github.com/near/NEPs/blob/master/neps/nep-0452.md). The **NEP-452** explains the **minimum interface** required to be implemented, as well as the expected functionality. + +--- + +## NEP-452 (Linkdrop Standard) + +[NEP-452](https://github.com/near/NEPs/blob/master/neps/nep-0452.md) is the blueprint for all linkdrop contracts on NEAR. It defines a **common set of rules** and **functions** that the contract MUST implement to be considered a linkdrop contract. + +:::tip + +Notice that the NEP-452 defines the **interface** and **expected behavior** of a linkdrop contract, but it does not dictate how the internal logic should be implemented + +Different linkdrop contracts can have different internal implementations while still adhering to the NEP-452 standard + +::: + +
+ +### Interface + +#### `get_key_balance` (*read-only*) + +Allows to query the amount of NEAR tokens assigned to a specific linkdrop key + +```ts +get_key_balance(key: string): string; +``` + +
+ +#### `get_key_information` (*read-only*) + +Returns information about a specific linkdrop key, including the amount of NEAR tokens assigned to it, the receiver ID, and whether the key has been claimed + +```ts +interface NFTData { + contract_id: string; + token_id: string; +} + +interface FTData { + contract_id: string; + amount: string; +} + +get_key_information(key: string): { required_gas: string, yoctonear: string, nft_list: NFTData[], ft_list: FTData[] }; +``` + +
+ +#### `claim` + +Allows a user to claim the assets associated with a specific key. The function transfers the NEAR tokens, NFTs, and FTs assigned to the provided `account_id`, which MUST exist prior to calling this method. + +> ⚠️ Users need to call this method signing the transaction with the **linkdrop key they received**. + +```ts +claim(account_id: string): boolean; +``` + +
+ +#### `create_account_and_claim` + +Allows a user to **create a new account** and **claim the assets** associated with a specific key. The function creates the new account with the provided `new_account_id` and transfers the NEAR tokens, NFTs, and FTs assigned to it. + +> ⚠️ Users need to call this method signing the transaction with the **linkdrop key they received**. + +```ts +create_account_and_claim(new_account_id: string, new_public_key: string): Promise; +``` \ No newline at end of file diff --git a/docs/primitives/lockup/introduction.md b/docs/primitives/lockup/introduction.md new file mode 100644 index 00000000000..9e708fcb446 --- /dev/null +++ b/docs/primitives/lockup/introduction.md @@ -0,0 +1,178 @@ +--- +id: introduction +title: Introduction +description: "Learn about Lockup contracts on NEAR – smart contracts that escrow tokens with time-based release schedules, supporting lockups, vesting, staking, and termination by foundation." +--- + +Lockup contracts act as escrows that hold tokens and release them gradually over time. They are widely used to manage employee compensation, investor vesting schedules, or long-term token allocations. + +Lockup contracts restrict token liquidity until predefined conditions are met by combining two key mechanisms: + +- **Lockup** – tokens remain locked until a certain date is reached. +- **Vesting** – tokens are made available to the user, but might be released gradually. + +Through lockup and vesting, projects can enforce predictable token release schedules that align incentives and improve transparency. + +--- + +## Lockup Schedule + +A lockup defines how tokens are released linearly over time. It is described by: + +- `lockup_timestamp` – when unlocking begins. +- `release_duration` – how long the unlocking lasts. + By the end, all tokens are available. +- `finish_timestamp = lockup_timestamp + release_duration` + +```mermaid +--- +config: + theme: "neutral" + xyChart: + width: 800 + height: 300 + showDataLabel: true + themeVariables: + xyChart: + plotColorPalette: '#000000, #FF0000' +--- +xychart + title "Linear Schedule" + x-axis [before, lockup_timestamp, finish_timestamp, after] + y-axis "Tokens Unlocked (in %)" 0 --> 100 + line [0, 0, 100, 100] +``` + +--- + +## Vesting Schedule + +Vesting adds additional conditions, typically used for employment or investment agreements: + +- `start_timestamp` – when vesting starts (e.g. hire date). +- `cliff_timestamp` – the first time tokens vest (e.g. 1 year). +- `end_timestamp` – when vesting completes. + +Example: +A **4-year vesting** with a **1-year cliff** means: + +- Year 1: nothing vests. +- At 1-year mark: 25% vests at once. +- Remaining 75% vests linearly for the remaining 3 years. + +```mermaid +--- +config: + theme: "neutral" + xyChart: + width: 800 + height: 300 + showDataLabel: true + themeVariables: + xyChart: + plotColorPalette: '#000000' +--- +xychart + title "Vested Schedule" + x-axis [before, start_timestamp, cliff_timestamp, cliff_timestamp, end_timestamp, after] + y-axis "Tokens Unlocked (in %)" 0 --> 100 + line [0, 0, 0, 25, 100, 100] +``` + +--- + +## Combined Schedule + +Lockup and vesting can be combined. Tokens become liquid only when both conditions allow: + +`liquidity_timestamp = max(lockup_timestamp, cliff_timestamp)` + +Depending on which event comes first, the outcome for the token release differs. + +### Scenario A: Lockup before Cliff + +In this case, the lockup timestamp occurs earlier than the cliff timestamp. Although the lockup schedule would normally allow tokens to start unlocking, the vesting cliff has not yet passed. As a result, no tokens are liquid until the cliff. + +It introduces three key timestamps: + +- `lockup_timestamp` – occurs earlier than the vesting cliff +- `cliff_timestamp` – comes later, so vesting delays liquidity +- `end_timestamp` – when vesting fully completes + +```mermaid +--- +config: + theme: "neutral" + xyChart: + width: 800 + height: 300 + showDataLabel: true + themeVariables: + xyChart: + plotColorPalette: '#000000' +--- +xychart + title "Combined Schedule: #A" + x-axis [before, lockup_timestamp, cliff_timestamp, cliff_timestamp, end_timestamp, after] + y-axis "Tokens Unlocked (in %)" 0 --> 100 + line [0, 0, 0, 25, 100, 100] +``` + +### Scenario B: Cliff before Lockup + +In this case, by the time the cliff is reached, 25% of tokens are considered vested. However, liquidity is still blocked because the lockup period has not ended. + +It introduces three key timestamps: + +- `cliff_timestamp` – occurs earlier than lockup +- `lockup_timestamp` – comes later and delays liquidity unlock +- `end_timestamp` – when vesting fully completes + +```mermaid +--- +config: + theme: "neutral" + xyChart: + width: 800 + height: 300 + showDataLabel: true + themeVariables: + xyChart: + plotColorPalette: '#000000' +--- +xychart + title "Combined Schedule: #B" + x-axis [before,cliff_timestamp, lockup_timestamp, lockup_timestamp, end_timestamp, after] + y-axis "Tokens Unlocked (in %)" 0 --> 100 + line [0, 0, 0, 25, 100, 100] +``` + +--- + +## Termination by Foundation + +When the `foundation_account_id` is specified at initialization, this account is granted the right to terminate vesting before its natural completion. The effect of termination depends on whether it happens before or after the vesting cliff. + +- If termination occurs before the cliff date, none of the tokens are considered vested and the entire allocation is refunded back to the foundation. + +- If termination happens after the cliff, the portion that has already vested up to that point remains with the owner, while all of the remaining unvested tokens are returned to the foundation. + +This ensures that the owner never receives more than what has already vested, while giving the foundation a mechanism to reclaim the locked portion in case of early termination of the agreement. + +You’ll discover real examples as you continue reading. + +--- + +## Staking with Locked Tokens + +The Lockup contract allows the owner to delegate tokens to a whitelisted staking pool, and it lets the owner to earn additional rewards while their base tokens remain locked. + +The process works as follows: + +- The owner selects a validator from the whitelist and stakes tokens through the lockup contract. + +- The staked amount itself remains locked according to the lockup and vesting schedules. + +- The validator generates staking rewards over time. + +A crucial distinction is that staking rewards are liquid immediately. They are not bound by the original lockup or vesting conditions. For example, if 1000 NEAR are locked and staked for one month, and 10 NEAR are earned as rewards, when the owner decides to unstake, the original 1000 NEAR follow the normal lockup and vesting restrictions, while any rewards already earned can be transferred directly to your account. \ No newline at end of file diff --git a/docs/primitives/lockup.md b/docs/primitives/lockup/lockup.md similarity index 52% rename from docs/primitives/lockup.md rename to docs/primitives/lockup/lockup.md index 14544963aa7..7713d6d8f32 100644 --- a/docs/primitives/lockup.md +++ b/docs/primitives/lockup/lockup.md @@ -1,207 +1,27 @@ --- id: lockup title: Lockup Contracts -hide_table_of_contents: false description: "Learn about Lockup contracts on NEAR – smart contracts that escrow tokens with time-based release schedules, supporting lockups, vesting, staking, and termination by foundation." --- -import {FeatureList, Column, Feature} from "@site/src/components/featurelist" +Looking to manage token vesting and lockup schedules? NEAR's Lockup contracts provide a robust solution for escrowing tokens with time-based release mechanisms. -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import { LantstoolLabel } from "@site/src/components/lantstool/LantstoolLabel/LantstoolLabel"; -import { TryOutOnLantstool } from "@site/src/components/lantstool/TryOutOnLantstool"; - -Lockup contracts act as escrows that hold tokens and release them gradually over time. They are widely used to manage employee compensation, investor vesting schedules, or long-term token allocations. - -Unlike [Fungible Tokens](ft.md), where transfers happen freely between accounts, lockup contracts restrict token liquidity until predefined conditions are met. -They combine two key mechanisms: - -- **Lockup** – tokens remain locked until a certain date is reached. -- **Vesting** – tokens are made available to the user, but might be released gradually. - -By combining these, projects can enforce predictable token release schedules that align incentives and improve transparency. - ---- - -## Core Concepts - -### Lockup Schedule - -A lockup defines how tokens are released linearly over time. It is described by: - -- `lockup_timestamp` – when unlocking begins. -- `release_duration` – how long the unlocking lasts. - By the end, all tokens are available. -- `finish_timestamp = lockup_timestamp + release_duration` - -```mermaid --- -config: - theme: "neutral" - xyChart: - width: 800 - height: 300 - showDataLabel: true - themeVariables: - xyChart: - plotColorPalette: '#000000, #FF0000' ---- -xychart - title "Linear Schedule" - x-axis [before, lockup_timestamp, finish_timestamp, after] - y-axis "Tokens Unlocked (in %)" 0 --> 100 - line [0, 0, 100, 100] -``` - ---- - -### Vesting Schedule - -Vesting adds additional conditions, typically used for employment or investment agreements: -- `start_timestamp` – when vesting starts (e.g. hire date). -- `cliff_timestamp` – the first time tokens vest (e.g. 1 year). -- `end_timestamp` – when vesting completes. +## Deploying a Lockup Contract -Example: -A **4-year vesting** with a **1-year cliff** means: +The simplest way to deploy a new lockup contract is to use the existing [global contract](../../smart-contracts/global-contracts.md) already published on NEAR. -- Year 1: nothing vests. -- At 1-year mark: 25% vests at once. -- Remaining 75% vests linearly for the remaining 3 years. +It is important to understand that the **total amount of tokens to be locked is determined by the balance of the account at the moment of deployment**. +Whatever tokens are in the account once you deploy the contract will become locked under the schedule you define. -```mermaid ---- -config: - theme: "neutral" - xyChart: - width: 800 - height: 300 - showDataLabel: true - themeVariables: - xyChart: - plotColorPalette: '#000000' ---- -xychart - title "Vested Schedule" - x-axis [before, start_timestamp, cliff_timestamp, cliff_timestamp, end_timestamp, after] - y-axis "Tokens Unlocked (in %)" 0 --> 100 - line [0, 0, 0, 25, 100, 100] -``` - ---- - -### Combined Schedule - -Lockup and vesting can be combined. Tokens become liquid only when both conditions allow: - -`liquidity_timestamp = max(lockup_timestamp, cliff_timestamp)` - -Depending on which event comes first, the outcome for the token release differs. - -#### Scenario A: Lockup before Cliff - -In this case, the lockup timestamp occurs earlier than the cliff timestamp. Although the lockup schedule would normally allow tokens to start unlocking, the vesting cliff has not yet passed. As a result, no tokens are liquid until the cliff. - -It introduces three key timestamps: - -- `lockup_timestamp` – occurs earlier than the vesting cliff -- `cliff_timestamp` – comes later, so vesting delays liquidity -- `end_timestamp` – when vesting fully completes - -```mermaid ---- -config: - theme: "neutral" - xyChart: - width: 800 - height: 300 - showDataLabel: true - themeVariables: - xyChart: - plotColorPalette: '#000000' ---- -xychart - title "Combined Schedule: #A" - x-axis [before, lockup_timestamp, cliff_timestamp, cliff_timestamp, end_timestamp, after] - y-axis "Tokens Unlocked (in %)" 0 --> 100 - line [0, 0, 0, 25, 100, 100] -``` - -#### Scenario B: Cliff before Lockup - -In this case, by the time the cliff is reached, 25% of tokens are considered vested. However, liquidity is still blocked because the lockup period has not ended. - -It introduces three key timestamps: - -- `cliff_timestamp` – occurs earlier than lockup -- `lockup_timestamp` – comes later and delays liquidity unlock -- `end_timestamp` – when vesting fully completes - -```mermaid ---- -config: - theme: "neutral" - xyChart: - width: 800 - height: 300 - showDataLabel: true - themeVariables: - xyChart: - plotColorPalette: '#000000' ---- -xychart - title "Combined Schedule: #B" - x-axis [before,cliff_timestamp, lockup_timestamp, lockup_timestamp, end_timestamp, after] - y-axis "Tokens Unlocked (in %)" 0 --> 100 - line [0, 0, 0, 25, 100, 100] -``` - ---- - -### Termination by Foundation - -When the `foundation_account_id` is specified at initialization, this account is granted the right to terminate vesting before its natural completion. The effect of termination depends on whether it happens before or after the vesting cliff. - -- If termination occurs before the cliff date, none of the tokens are considered vested and the entire allocation is refunded back to the foundation. - -- If termination happens after the cliff, the portion that has already vested up to that point remains with the owner, while all of the remaining unvested tokens are returned to the foundation. - -This ensures that the owner never receives more than what has already vested, while giving the foundation a mechanism to reclaim the locked portion in case of early termination of the agreement. - -You’ll discover real examples as you continue reading. - ---- - -### Staking with Locked Tokens - -The Lockup contract allows the owner to delegate tokens to a whitelisted staking pool, and it lets the owner to earn additional rewards while their base tokens remain locked. - -The process works as follows: - -- The owner selects a validator from the whitelist and stakes tokens through the lockup contract. - -- The staked amount itself remains locked according to the lockup and vesting schedules. - -- The validator generates staking rewards over time. - -A crucial distinction is that staking rewards are liquid immediately. They are not bound by the original lockup or vesting conditions. For example, if 1000 NEAR are locked and staked for one month, and 10 NEAR are earned as rewards, when the owner decides to unstake, the original 1000 NEAR follow the normal lockup and vesting restrictions, while any rewards already earned can be transferred directly to your account. - -You’ll discover real examples as you continue reading. - ---- - -## Using the Contract - -### Deploying Your Own Contract - -Lockup contracts on NEAR are deployed as global contracts by hash. This means you don’t have to compile and upload the WASM yourself, instead you can use the published code hash to ensure consistency across deployments. - -The critical point is that the locked balance is determined at this moment. Whatever tokens are already on the contract account are locked under the schedule you define. This means that if you are, for example, a company setting up a lockup for an employee, you must first create and fund the lockup account with the intended amount of tokens, and then deploy. +This means that you must always **first create and fund the lockup account** with the intended amount of tokens, and only after that deploy the contract. ```bash +# Create and fund the lockup account +near create-account --useAccount --initialBalance + +# Deploy the lockup contract near contract deploy use-global-hash CAvU5MYQ4xk1SjFvbnQDQUj6qehuW5YhU3FXA6GMddCx with-init-call new json-args '{ "owner_account_id": "employee.near", "lockup_duration": "0", diff --git a/docs/primitives/nft.md b/docs/primitives/nft/nft.md similarity index 93% rename from docs/primitives/nft.md rename to docs/primitives/nft/nft.md index e20e79c80d2..1517f01e070 100644 --- a/docs/primitives/nft.md +++ b/docs/primitives/nft/nft.md @@ -1,7 +1,6 @@ --- id: nft -title: Non-Fungible Tokens (NFT) -hide_table_of_contents: false +title: Using NFTs description: "Learn about NEAR non-fungible tokens (NFT) following NEP-171 and NEP-177 standards - mint, transfer, query, and trade unique digital assets with comprehensive examples." --- @@ -15,18 +14,7 @@ import { TryOutOnLantstool } from "@site/src/components/lantstool/TryOutOnLantst import MintNFT from "@site/src/components/tools/NonFungibleToken/MintNFT"; - -In contrast with fungible tokens, non-fungible tokens (NFT) are unitary and therefore unique. This makes NFTs ideal to represent ownership of assets such as a piece of digital content, or a ticket for an event. - -As with fungible tokens, NFTs are **not stored** in the user's wallet, instead, each NFT lives in a **NFT contract**. The NFT contract works as a bookkeeper, this is: it is in charge of handling the creation, storage and transfers of NFTs. - -In order for a contract to be considered a NFT-contract it has to follow the [**NEP-171 and NEP-177 standards**](https://github.com/near/NEPs/tree/master/neps/nep-0171.md). The **NEP-171** & **NEP-177** standards explain the **minimum interface** required to be implemented, as well as the expected functionality. - -:::info NFT & Marketplaces - -Be mindful of not confusing an NFT with an NFT-marketplace. NFT simply store information (metadata), while NFT-marketplaces are contracts where NFT can be listed and exchanged for a price. - -::: +Wanting to use Non-Fungible Tokens (NFT) in your dApp? Here you will find all the information you need to get started creating your own tokens, registering users, transferring tokens, and integrating them into your smart contracts. --- @@ -51,7 +39,7 @@ If you want to deploy your own NFT contract, you can create one using our [refer ### Global Contract -You can deploy a new Non-Fungible Token using our global NFT contract - a pre-deployed [standard NFT contract](https://github.com/near-examples/NFT) that you can reuse. [Global contracts](../smart-contracts/global-contracts.md) are deployed once and can be reused by any account without incurring high storage costs. +You can deploy a new Non-Fungible Token using our global NFT contract - a pre-deployed [standard NFT contract](https://github.com/near-examples/NFT) that you can reuse. [Global contracts](../../smart-contracts/global-contracts.md) are deployed once and can be reused by any account without incurring high storage costs. @@ -91,12 +79,18 @@ Deploying by **hash** creates an immutable contract that never changes. Deployin --- ## Minting a NFT -To create a new NFT (a.k.a. minting it) you will call the `nft_mint` method passing as arguments the metadata that defines the NFT. +To create a new NFT (a.k.a. minting it) you will call the `nft_mint` method passing as arguments the metadata that defines the NFT. Here is a simple form that you can use to mint your own NFT: + + + + +
+ + Manual Interaction + +Here is how to directly interact with the factory contract through your application: - - - ```js @@ -188,6 +182,9 @@ Values of gas and deposit might vary depending on which NFT contract you are cal ::: + +
+
### Minting Collections diff --git a/docs/primitives/nft/standard.md b/docs/primitives/nft/standard.md new file mode 100644 index 00000000000..0269d9965e0 --- /dev/null +++ b/docs/primitives/nft/standard.md @@ -0,0 +1,186 @@ +--- +id: standard +title: The Standard +description: "Learn how Non-Fungible Tokens (NFT) are defined on NEAR" +--- + +In contrast with fungible tokens, non-fungible tokens (NFT) are unitary and therefore unique. This makes NFTs ideal to represent ownership of assets such as a piece of digital content, or a ticket for an event. + +As with fungible tokens, NFTs are **not stored** in the user's wallet, instead, each NFT lives in a **NFT contract**. The NFT contract works as a bookkeeper, being in charge of creating, storing and transferring NFTs. + +:::info NFT & Marketplaces + +Be mindful of not confusing an NFT with an NFT-marketplace. NFT simply store information (metadata), while NFT-marketplaces are contracts where NFT can be listed and exchanged for a price. + +::: + +--- + +## NEP-171 (NFT Interface) + +[NEP-171](https://github.com/near/NEPs/tree/master/neps/nep-0171.md) is the blueprint for all non-fungible tokens on NEAR. It defines a **common set of rules** and **functions** that the contract MUST implement to be considered a non-fungible token contract. + +:::tip + +Notice that the NEP-171 defines the **interface** and **expected behavior** of a non-fungible token contract, but it does not dictate how the internal logic should be implemented + +Different NFT contracts can have different internal implementations while still adhering to the NEP-171 standard + +::: + +
+ +### Interface + +#### `nft_token` (*read-only*) + +Returns the token information for a given `token_id` + +```ts +nft_token(token_id: string): { token_id: string, owner_id: string } | null +``` + +
+ +#### `nft_transfer` +Transfers the `token_id` from the caller to the `receiver_id`, optionally the function can include a `memo` field to provide additional information to the contract + +The caller must be the **either** the current owner of the token or an **account** that has been **approved to transfer** the token on behalf of the owner, such as a marketplace contract. The approval mechanism is defined in the [NEP-178 standard](https://github.com/near/NEPs/blob/master/neps/nep-0178.md). + +> *Requirement: The caller must attach [exactly 1 yoctoNEAR](../../smart-contracts/security/one_yocto.md) to the call* + +```ts +nft_transfer(receiver_id: string, token_id: string, approval_id?: number, memo: string?): void +``` + +
+ +#### `nft_transfer_call` + +The function transfers the `token_id` to the `receiver_id` **and calls the method `nft_on_transfer(sender_id, previous_owner_id, token_id, msg)`** on `receiver_id`. + +Optionally the function can include a `memo` for the NFT contract, and a `msg` field to which will be sent to the receiver contract. + +> πŸ“– This function is useful to transfer NFTs to a contract and trigger some action on the receiver side in a single transaction, thus acting as **attaching NFTs to a function call** + +```ts +nft_transfer_call(receiver_id: string, token_id: string, approval_id?: number, memo?: string, msg: string): Promise {} +``` + +
+ + nft_on_transfer + + Smart contracts expecting to **receive** Non-Fungible Tokens **must** implement this method. + + The method **must** return a boolean value indicating whether the token should be returned to the sender (`true`) or not (`false`). + + ```ts + nft_on_transfer(sender_id: string, previous_owner_id: string, token_id: string, msg: string): boolean + ``` + + ⚠️ Note that this method does not need to be implemented by the NFT contract itself, but rather by any contract that expects to receive non-fungible tokens + +
+ +
+ +#### `nft_resolve_transfer` + +This method is used as a [callback](../../smart-contracts/anatomy/crosscontract.md#callback-function) to resolve the `nft_transfer_call` transaction, handling refunds if necessary. + +It must return `true` if the token was successfully transferred to `receiver_id`, or `false` if the token was returned to `owner_id`. + +```js +nft_resolve_transfer(owner_id: string, receiver_id: string, token_id: string, approved_account_ids?: Record): boolean +``` + +--- + +## NEP-177 (NFT Metadata) + +[NEP-177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) is an extension to the NEP-171 standard that defines the **metadata** for both non-fungible tokens and non-fungible token contracts. + +Metadata provides **key information** , such as the contract's **name** or the NFT's **title**. Particularly, the following fields MUST be included in the smart contract and token's metadata: + +```ts +type NFTContractMetadata = { + spec: string, // required, essentially a version like "nft-1.0.0" + name: string, // required, ex. "Mochi Rising β€” Digital Edition" or "Metaverse 3" + symbol: string, // required, ex. "MOCHI" + icon: string|null, // Data URL + base_uri: string|null, // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs + reference: string|null, // URL to a JSON file with more info + reference_hash: string|null, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} + +type TokenMetadata = { + title: string|null, // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055" + description: string|null, // free-form description + media: string|null, // URL to associated media, preferably to decentralized, content-addressed storage + media_hash: string|null, // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included. + copies: number|null, // number of copies of this set of metadata in existence when token was minted. + issued_at: number|null, // When token was issued or minted, Unix epoch in milliseconds + expires_at: number|null, // When token expires, Unix epoch in milliseconds + starts_at: number|null, // When token starts being valid, Unix epoch in milliseconds + updated_at: number|null, // When token was last updated, Unix epoch in milliseconds + extra: string|null, // anything extra the NFT wants to store on-chain. Can be stringified JSON. + reference: string|null, // URL to an off-chain JSON file with more info. + reference_hash: string|null // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} +``` + +--- + +## NEP-178 (NFT Approval Management) + +[NEP-178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) is an extension to the NEP-171 standard that defines the **approval management** for non-fungible tokens. + +The approval mechanism allows the owner of an NFT to authorize another account (for example, a marketplace contract) to transfer the token on their behalf. + +
+ +### Interface + +#### `nft_is_approved` (*read-only*) + +Returns whether an `approved_account_id` is actually approved to transfer the `token_id` on behalf of the token owner. If `approval_id` is provided, it will also check that the approval ID matches. + +```ts +nft_is_approved(token_id: string, approved_account_id: string, approval_id?: number): boolean +``` + +
+ +#### `nft_approve` + +Grants approval to `account_id` to transfer the `token_id` on behalf of the token owner. Optionally, the function can include a `msg` field to provide additional information to the contract. + +> *Requirement: The caller must attach a deposit of at least `1 yoctoNEAR` plus the storage cost for adding the new approval* + +```ts +nft_approve(token_id: string, account_id: string, msg?: string): void +``` + +
+ +#### `nft_revoke` +Revokes approval for `account_id` to transfer the `token_id` on behalf of the token owner. + +> *Requirement: The caller must attach [exactly 1 yoctoNEAR](../../smart-contracts/security/one_yocto.md) to the call* + +```ts +nft_revoke(token_id: string, account_id: string): void +``` + +
+ +#### `nft_revoke_all` + +Revokes all approvals for the `token_id`. + +> *Requirement: The caller must attach [exactly 1 yoctoNEAR](../../smart-contracts/security/one_yocto.md) to the call* + +```ts +nft_revoke_all(token_id: string): void +``` \ No newline at end of file diff --git a/docs/primitives/what-is.md b/docs/primitives/what-is.md index 088e6241eb9..39c95d30dc5 100644 --- a/docs/primitives/what-is.md +++ b/docs/primitives/what-is.md @@ -14,7 +14,7 @@ Primitives are fundamental building blocks that can be combined to create a full --- #### Fungible Tokens (FT) -[Fungible tokens](./ft.md) represent an **asset** on a blockchain that is **interchangeable**. Besides the native NEAR token, users can issue their own fungible tokens or use those that are already present in the ecosystem. +[Fungible tokens](./ft/ft.md) represent an **asset** on a blockchain that is **interchangeable**. Besides the native NEAR token, users can issue their own fungible tokens or use those that are already present in the ecosystem. :::tip Fungible Tokens are ideal to create **reward systems**, **fair tickets** and any other type of **token**. @@ -23,7 +23,7 @@ Fungible Tokens are ideal to create **reward systems**, **fair tickets** and any
#### Non Fungible Tokens (NFT) -In contrast with fungible tokens, each [non-fungible token (NFT)](./nft.md) is **unitary** and therefore **unique**. Users can create their own non-fungible token, transfer to other users, or exchange them in marketplaces. +In contrast with fungible tokens, each [non-fungible token (NFT)](./nft/nft.md) is **unitary** and therefore **unique**. Users can create their own non-fungible token, transfer to other users, or exchange them in marketplaces. :::tip NFTs are ideal to represent **ownership of assets** such as **collectibles**, **event tickets** and other unique assets. @@ -41,7 +41,7 @@ DAOs are ideal to create **decentralized governance**, **funding**, and **decisi
### LinkDrops -[LinkDrops](./linkdrop.md) are an easy way to **distribute digital assets** (NFTs, FTs) via links. You simply **provide a link** for users and they can **claim** your drop. +[LinkDrops](./linkdrop/linkdrop.md) are an easy way to **distribute digital assets** (NFTs, FTs) via links. You simply **provide a link** for users and they can **claim** your drop. :::tip LinkDrops are ideal to do **drops**, and **onboard new users** into Web3 apps. diff --git a/docs/protocol/access-keys.md b/docs/protocol/access-keys.md index 1f81c9741d1..74b53ed07c4 100644 --- a/docs/protocol/access-keys.md +++ b/docs/protocol/access-keys.md @@ -90,7 +90,7 @@ It works as follows: Your main account and your funds will never be at risk, as the keys can only be used to call the `create_account` method. :::tip -This is the basic principle behind [NEAR Drops](../primitives/linkdrop.md), a way to distribute assets to a large number of users +This is the basic principle behind [NEAR Drops](../primitives/nft/nft.md), a way to distribute assets to a large number of users :::
diff --git a/docs/smart-contracts/anatomy/environment.md b/docs/smart-contracts/anatomy/environment.md index 157cfd57126..d376a112961 100644 --- a/docs/smart-contracts/anatomy/environment.md +++ b/docs/smart-contracts/anatomy/environment.md @@ -120,7 +120,7 @@ During a simple transaction (no [cross-contract calls](../anatomy/crosscontract. *You can access information about the users interacting with your smart contract* :::tip -In most scenarios you will **only need to know the predecessor**. However, there are situations in which the signer is very useful. For example, when adding [NFTs](../../primitives/nft.md) into [this marketplace](https://github.com/near-examples/nft-tutorial/blob/7fb267b83899d1f65f1bceb71804430fab62c7a7/market-contract/src/nft_callbacks.rs#L42), the contract checks that the `signer`, i.e. the person who generated the transaction chain, is the NFT owner. +In most scenarios you will **only need to know the predecessor**. However, there are situations in which the signer is very useful. For example, when adding [NFTs](../../primitives/nft/nft.md) into [this marketplace](https://github.com/near-examples/nft-tutorial/blob/7fb267b83899d1f65f1bceb71804430fab62c7a7/market-contract/src/nft_callbacks.rs#L42), the contract checks that the `signer`, i.e. the person who generated the transaction chain, is the NFT owner. ::: --- diff --git a/docs/smart-contracts/security/one_yocto.md b/docs/smart-contracts/security/one_yocto.md index 1e7b471535f..6e4c20b5388 100644 --- a/docs/smart-contracts/security/one_yocto.md +++ b/docs/smart-contracts/security/one_yocto.md @@ -9,7 +9,7 @@ NEAR uses a system of [Access Keys](../../protocol/access-keys.md) to simplify h When a user [signs in on a website](../../web3-apps/tutorials/web-login/wallet-selector.md#user-sign-in--sign-out) to interact with your contract, what actually happens is that a `Function Call` key is created and stored in the website. Since the website has access to the `Function Call` key, it can use it to call the authorized methods as it pleases. While this is very user friendly for most cases, it is important to be careful in scenarios involving -transferring of valuable assets like [NFTs](../../primitives/nft.md) or [FTs](../../primitives/ft.md). In such cases, you need to ensure that +transferring of valuable assets like [NFTs](../../primitives/nft/nft.md) or [FTs](../../primitives/ft/ft.md). In such cases, you need to ensure that the person asking for the asset to be transfer is **actually the user**. One direct and inexpensive way to ensure that the user is the one calling is by requiring to attach `1 yⓃ`. In this case, the user will be diff --git a/docs/tools/sdk.md b/docs/tools/sdk.md index 54dd2e52dfb..47ed6c4738c 100644 --- a/docs/tools/sdk.md +++ b/docs/tools/sdk.md @@ -1,7 +1,6 @@ --- id: sdk title: NEAR SDK -hide_table_of_contents: false description: "Choose an SDK to start building contracts." --- diff --git a/docs/tutorials/auction/3.1-nft.md b/docs/tutorials/auction/3.1-nft.md index 89b78b612a4..ff146cd106c 100644 --- a/docs/tutorials/auction/3.1-nft.md +++ b/docs/tutorials/auction/3.1-nft.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import {Github, Language} from "@site/src/components/UI/Codetabs" -No one will enter an auction if there's nothing to win, so let's add a prize. Why not an [NFT](../../primitives/nft.md)? NFTs are uniquely identifiable, easily swappable and their logic comes from an external contract so the prize will exist without the auction contract. Let's get to work! +No one will enter an auction if there's nothing to win, so let's add a prize. Why not an [NFT](../../primitives/nft/nft.md)? NFTs are uniquely identifiable, easily swappable and their logic comes from an external contract so the prize will exist without the auction contract. Let's get to work! --- diff --git a/docs/tutorials/auction/3.2-ft.md b/docs/tutorials/auction/3.2-ft.md index dec8fc79bd3..bc482c9b5e0 100644 --- a/docs/tutorials/auction/3.2-ft.md +++ b/docs/tutorials/auction/3.2-ft.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import {Github, Language} from "@site/src/components/UI/Codetabs" -To further develop this contract we will introduce another primitive: [fungible tokens](../../primitives/ft.md). Instead of placing bids in $NEAR tokens, they will be placed in FTs. This may be useful if, for example, an auctioneer wants to keep the bid amounts constant in terms of dollars as an auction is carried out, so bids can be placed in stablecoins such as $USDC. Another use case is if a project like Ref Finance was holding its own auction and wanted the auction to happen in its project's token $REF. +To further develop this contract we will introduce another primitive: [fungible tokens](../../primitives/ft/ft.md). Instead of placing bids in $NEAR tokens, they will be placed in FTs. This may be useful if, for example, an auctioneer wants to keep the bid amounts constant in terms of dollars as an auction is carried out, so bids can be placed in stablecoins such as $USDC. Another use case is if a project like Ref Finance was holding its own auction and wanted the auction to happen in its project's token $REF. --- @@ -40,7 +40,7 @@ We want to only accept bids in one type of fungible token; accepting many differ ## Accepting bids in FTs -When we were making bids in $NEAR tokens we would call the auction contract directly and attach $NEAR tokens to the call. With fungible tokens, since an account's balance lives on a separate contract, we call the FT contract which then calls the auction contract and transfers tokens. The method on the FT contract to do this is named `ft_transfer_call` and it will always call a method in the target contract named `ft_on_transfer`. Take a look [here](../../primitives/ft.md#attaching-fts-to-a-call) for more information. +When we were making bids in $NEAR tokens we would call the auction contract directly and attach $NEAR tokens to the call. With fungible tokens, since an account's balance lives on a separate contract, we call the FT contract which then calls the auction contract and transfers tokens. The method on the FT contract to do this is named `ft_transfer_call` and it will always call a method in the target contract named `ft_on_transfer`. Take a look [here](../../primitives/ft/ft.md#attaching-fts-to-a-call) for more information. ![ft_transfer_call-flow](/assets/docs/tutorials/auction/auction-ft-transfer.png) @@ -223,7 +223,7 @@ When the contract is deployed it is initialized with `new_default_meta` which se ## Registering users in the FT contract -For one to receive fungible tokens, first their account ID must be [registered](../../primitives/ft.md#registering-a-user) in the FT contract. A user has to register in an FT contract to pay for the storage used to track their amount of tokens. By default, a contract pays for its own storage, but not requiring a user to register and pay for storage would drain the contract of $NEAR tokens. When the contract is live we don't need to register the accounts that we transfer tokens back to since to make a bid in the first place they would have needed to be registered, but we do need to register the auction contract in the FT contract to receive bids and the auctioneer to receive the funds at the end of the auction. It is most convenient to register users from the frontend rather than the contract. +For one to receive fungible tokens, first their account ID must be [registered](../../primitives/ft/ft.md#registering-a-user) in the FT contract. A user has to register in an FT contract to pay for the storage used to track their amount of tokens. By default, a contract pays for its own storage, but not requiring a user to register and pay for storage would drain the contract of $NEAR tokens. When the contract is live we don't need to register the accounts that we transfer tokens back to since to make a bid in the first place they would have needed to be registered, but we do need to register the auction contract in the FT contract to receive bids and the auctioneer to receive the funds at the end of the auction. It is most convenient to register users from the frontend rather than the contract. In our tests, since we are creating a new fungible token and new accounts we will actually have to register every account that will interact with FTs. diff --git a/docs/tutorials/examples/factory.md b/docs/tutorials/examples/factory.md index 6cfc553d352..40117de9094 100644 --- a/docs/tutorials/examples/factory.md +++ b/docs/tutorials/examples/factory.md @@ -70,7 +70,7 @@ The following command will create the `sub.`, which will have a near contract call-function as-transaction deploy json-args '{"name": "sub"}' prepaid-gas '100.0 Tgas' attached-deposit '0.2 NEAR' sign-as network-config testnet sign-with-keychain send ``` -By default, the global contract is the [Fungible Token](../../primitives/ft.md#global-contracts) primitive contract `ft.globals.primitives.testnet`. To initilize the contract, you can call its `new_default_meta` method: +By default, the global contract is the [Fungible Token](../../primitives/ft/ft.md#global-contracts) primitive contract `ft.globals.primitives.testnet`. To initilize the contract, you can call its `new_default_meta` method: ```bash near contract call-function as-transaction sub. new_default_meta json-args '{"owner_id": "", "total_supply": "100000000000000000000000000"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as network-config testnet sign-with-keychain send diff --git a/docs/tutorials/examples/near-drop.md b/docs/tutorials/examples/near-drop.md index 31c11a8694d..1d36a6e7efa 100644 --- a/docs/tutorials/examples/near-drop.md +++ b/docs/tutorials/examples/near-drop.md @@ -17,7 +17,7 @@ Particularly, it shows: :::tip -This example showcases a simplified version of the contract that both [Keypom](https://keypom.xyz/) and the [Token Drop Utility](https://dev.near.org/tools?tab=linkdrops) use to distribute tokens to users +This example showcases a simplified version of the contract that both [Keypom](https://github.com/keypom/keypom) and the [Token Drop Utility](https://dev.near.org/tools?tab=linkdrops) use to distribute tokens to users ::: @@ -65,7 +65,7 @@ Creates the `account_id`, and then drops the tokens into it ## Contract's State -We can see in the contract's state that the contract keeps track of different `PublicKeys`, and links them to a specific `DropId`, which is simply an identifier for a `Drop` (see below). +We can see in the contract's state that the contract keeps track of different `PublicKeys`, and links them to a specific `DropId`, which is simply an identifier for a `Drop` (see below). - `top_level_account`: The account that will be used to create new accounts, generally it will be `testnet` or `mainnet` - `next_drop_id`: A simple counter used to assign unique identifiers to each drop diff --git a/website/sidebars.js b/website/sidebars.js index 072ec767447..5154903a163 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -155,10 +155,12 @@ const sidebar = { { "Getting Started": [ "ai/shade-agents/getting-started/introduction", - { "Quickstart": [ - "ai/shade-agents/getting-started/quickstart/deploying", - "ai/shade-agents/getting-started/quickstart/components", - ]}, + { + "Quickstart": [ + "ai/shade-agents/getting-started/quickstart/deploying", + "ai/shade-agents/getting-started/quickstart/components", + ] + }, ] }, { @@ -446,15 +448,35 @@ const sidebar = { }, items: [ { type: 'link', label: 'Introduction', href: '/primitives/what-is' }, - 'primitives/ft', - 'primitives/nft', + { + 'Fungible Tokens (FT)': [ + 'primitives/ft/standard', + 'primitives/ft/ft' + ] + }, + { + 'Non-Fungible Tokens (NFT)': [ + 'primitives/nft/standard', + 'primitives/nft/nft' + ] + }, + { + 'Linkdrops': [ + 'primitives/linkdrop/standard', + 'primitives/linkdrop/linkdrop' + ] + }, 'protocol/network/staking', - 'primitives/linkdrop', 'primitives/oracles', 'primitives/dao', 'primitives/dex', 'primitives/did', - 'primitives/lockup', + { + 'Lockup Contracts': [ + 'primitives/lockup/introduction', + 'primitives/lockup/lockup', + ] + } ], }, { diff --git a/website/src/components/UI/Card/Card.module.scss b/website/src/components/UI/Card/Card.module.scss index 0ad9ff149fb..e3a63493e29 100644 --- a/website/src/components/UI/Card/Card.module.scss +++ b/website/src/components/UI/Card/Card.module.scss @@ -1,5 +1,6 @@ .card { - margin: 0; + margin: var(--space-4) 0; + padding: var(--space-2) 0; border-radius: var(--radius-card); border: var(--border-card); background: var(--color-bg-surface); diff --git a/website/src/components/tools/FungibleToken/CreateTokenForm.jsx b/website/src/components/tools/FungibleToken/CreateTokenForm.jsx index e3568e2084f..31205620a7d 100644 --- a/website/src/components/tools/FungibleToken/CreateTokenForm.jsx +++ b/website/src/components/tools/FungibleToken/CreateTokenForm.jsx @@ -194,7 +194,7 @@ const CreateTokenForm = ({ reload = () => { } }) => { }; return ( - +
{ if (!drops || drops.length === 0) { return ( - +

Your Drops

πŸ“¦
@@ -40,7 +40,7 @@ const ListTokenDrop = ({ drops }) => { } return ( - +

Your Drops

{drops.map((drop, index) => { diff --git a/website/src/components/tools/NonFungibleToken/index.jsx b/website/src/components/tools/NonFungibleToken/index.jsx index d2aa72be12f..af160cf23de 100644 --- a/website/src/components/tools/NonFungibleToken/index.jsx +++ b/website/src/components/tools/NonFungibleToken/index.jsx @@ -14,7 +14,6 @@ const NonFungibleToken = ({ This tool allows you to mint Non-Fungible Tokens

-
); diff --git a/website/src/components/tools/index.jsx b/website/src/components/tools/index.jsx index c32d9c38d6e..50813d2a8e7 100644 --- a/website/src/components/tools/index.jsx +++ b/website/src/components/tools/index.jsx @@ -135,7 +135,7 @@ const Tools = () => { }, [fetchTokens, processFT, processNFT, signedAccountId]); - return <> + return
reload(d, 'fts')} /> @@ -157,7 +157,7 @@ const Tools = () => { - +
} export default Tools; \ No newline at end of file