diff --git a/docs/contracts/overview/NFT/create-nft-collection.md b/docs/contracts/overview/NFT/create-nft-collection.md index 8ec0de0f4..b33036c4b 100644 --- a/docs/contracts/overview/NFT/create-nft-collection.md +++ b/docs/contracts/overview/NFT/create-nft-collection.md @@ -4,3 +4,49 @@ sidebar_position: 1 --- # Create a Non Fungible Token + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +// modules +import { + LSP8IdentifiableDigitalAsset +} from "@lukso/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol"; + +// constants +import { + _LSP8_TOKENID_FORMAT_NUMBER +} from "@lukso/lsp8-contracts/contracts/LSP8Constants.sol"; +import { + _LSP4_TOKEN_TYPE_COLLECTION +} from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol"; + +contract BasicNFTCollection is LSP8IdentifiableDigitalAsset { + constructor( + string memory nftCollectionName, + string memory nftCollectionSymbol, + address contractOwner + ) + LSP8IdentifiableDigitalAsset( + nftCollectionName, + nftCollectionSymbol, + contractOwner, + _LSP4_TOKEN_TYPE_COLLECTION, + _LSP8_TOKENID_FORMAT_NUMBER + ) + { + // contract logic goes here... + } +} +``` + +## LSP8 NFT extensions + +The `@lukso/lsp8-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that can be added through inheritance. This enables to include specific functionalities for building your token. + +| Extension contract | Description | +| :------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | +| [`LSP8Burnable.sol`](../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md) | exposes a public `burn(...)` function that allows any NFT holder or operator to burn a specific NFT tokenId. | +| [`LSP8CappedSupply.sol`](../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md) | enable to specify a maximum supply on deployment / initialization, which cap the maximum amount of NFT that can be minted in the collection. | +| [`LSP8Enumerable.sol`](../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md) | functionality to enumerate the list of NFTs in a collection. | diff --git a/docs/contracts/overview/NFT/customise-transfer-behaviour.md b/docs/contracts/overview/NFT/customise-transfer-behaviour.md index 2d9669be4..5ba93b91e 100644 --- a/docs/contracts/overview/NFT/customise-transfer-behaviour.md +++ b/docs/contracts/overview/NFT/customise-transfer-behaviour.md @@ -4,3 +4,5 @@ sidebar_position: 2 --- # Customize transfer behaviour + +The `LSP8IdenfitiableDigitalAsset` contract implementation includes the `_beforeTokenTransfer` and `_afterTokenTransfer` functions that offer the ability to specify custom logic that can run before or after the token transfer has happen (= before or after the balances in the contract state have been updated). diff --git a/docs/contracts/overview/NFT/index.md b/docs/contracts/overview/NFT/index.md index f3a0263d8..05ae5e053 100644 --- a/docs/contracts/overview/NFT/index.md +++ b/docs/contracts/overview/NFT/index.md @@ -8,24 +8,52 @@ import TabItem from '@theme/TabItem'; # LSP8 Identifiable Digital Asset -The **LSP8 Identifiable Digital Asset** contract is the newest advanced version of the existing ERC NFT standards, such as ERC721. +:::danger Deprecation of `LSP8CompatibleERC721` + +The `LSP8CompatibleERC721` contracts have been deprecated and deleted from the [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) package since version `0.15.0`, because of their unsafe nature and [security considerations (See PR #845 for more details)](https://github.com/lukso-network/lsp-smart-contracts/pull/845#issuecomment-1888671461). -LSP8 identifiable digital assets represent **N**on **F**ungible **T**okens (NFTs) that can be uniquely traded. +They are not recommended to be used. However, if you want to still use them, they remain available in the version [`0.14.0`](https://github.com/lukso-network/lsp-smart-contracts/releases/tag/lsp-smart-contracts-v0.14.0). + +::: -and given metadata using the **[ERC725Y Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y)**. -Each NFT is identified with a tokenId, based on **[ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol)**. +The **LSP8 Identifiable Digital Asset** contract is the newest advanced version of the existing ERC NFT standards, such as ERC721. LSP8 identifiable digital assets represent **N**on **F**ungible **T**okens (NFTs) that can be uniquely traded. Each NFT is identified with a tokenId, based on **[ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol)** and can also have its own metadata set using the **[`setDataForTokenId(...)`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatafortokenid)** function. A **bytes32** value is used for tokenId to allow many uses of token identification, including numbers, contract addresses, and hashed values (i.e., serial numbers). -## Comparisons with ERC721 +## Installation & Usage -:::danger Deprecation of `LSP8CompatibleERC721` +The LSP8 smart contracts and their ABIs are available are available in their own individual package. To use them, install `@lukso/lsp8-contracts` as a dependency in your project. -The `LSP8CompatibleERC721` contracts have been deprecated and deleted from the [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) package since version `0.15.0`, because of their unsafe nature and [security considerations (See PR #845 for more details)](https://github.com/lukso-network/lsp-smart-contracts/pull/845#issuecomment-1888671461). + + -They are not recommended to be used. However, if you want to still use them, they remain available in the version [`0.14.0`](https://github.com/lukso-network/lsp-smart-contracts/releases/tag/lsp-smart-contracts-v0.14.0). +``` +npm install @lukso/lsp8-contracts +``` -::: + + + +``` +yarn add @lukso/lsp8-contracts +``` + + + + +``` +pnpm add @lukso/lsp8-contracts +``` + + + + +`LSP8IdentifiableDigitalAsset.sol` is an `abstract` contract that is not deployable as is, because it does not contain any public functions by default to manage token supply (_e.g: no public `mint(...)` or `burn(...)` functions_). You can either: + +- the `LSP8Mintable` preset contract that contains a public `mint(...)` function callable only by the contract's owner. +- or extend the `LSP8IdentifiableDigitalAsset` contract (_see below_) and create your own supply mechanism by defining public methods that use the internal `_mint(...)` and `_burn(...)` functions. + +## Comparisons with ERC721 @@ -61,237 +89,3 @@ In comparison ERC721 has: All of the above functions can be used by both the owner of the token id or by the operator of the token id in order to transfer the ERC721 token. To be mentioned, both functions `safeTransferFrom(...)` have a hook that calls the recipient contract. Looking at LSP7 & LSP8 we have unified `transfer(...)` & `transferBatch(...)` functions in both contracts. Those functions contain a hook which is executed conditionally and can be used in any of the above cases. - -## LSP8 NFT extensions - -The `@lukso/lsp8-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that enables to include functionalities for building your token through inheritance. - -- [`LSP8Burnable.sol](../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md)`: exposes a public `burn(...)` function that allows any NFT holder or operator to burn a specific NFT tokenId. -- [`LSP8CappedSupply.sol](../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md)`: enable to specify a maximum supply on deployment / initialization, which cap the maximum amount of NFT that can be minted in the collection. -- [`LSP8Enumerable.sol](../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md)`: functionality to enumerate the list of NFTs in a collection. - -## Custom logic for transfers - -The `LSP8IdenfitiableDigitalAsset` contract implementation includes the `_beforeTokenTransfer` and `_afterTokenTransfer` functions that offer the ability to specify custom logic that can run before or after the token transfer has happen (= before or after the balances in the contract state have been updated). - -## Setting metadata for one or multiple tokenIds - -The function [`setDataBatchForTokenIds(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatchfortokenids) can be used to set multiple data key-value pairs at once for one or multiple tokenIds. - -This function is flexible enough to enable to set one or multiple [data key-value](/standards/erc725).md#erc725y-generic-data-keyvalue-store) pairs for: - -### Case 1: a single tokenId - -To set for instance 3 x data key-value pairs for the same `tokenId`, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` will be as follow: - - - - - -```solidity -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.12; - -import { - ILSP8IdentifiableDigitalAsset as ILSP8 -} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol"; -import { - _LSP4_METADATA_KEY -} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; - -bytes32 constant _NFT_ICON_DATA_KEY = keccak256("NFTIcon"); -bytes32 constant _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256("NFTMarketplaceURLs"); - -bytes32 constant _TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe; - -function setMultipleDataForSingleTokenId( - ILSP8 lsp8Contract, - bytes memory lsp4MetadataValue, - bytes memory nftIconValue, - bytes memory nftMarketPlaceURLsValue -) { - bytes32[] memory tokenIdsToUpdate = new bytes32[](3); - bytes32[] memory dataKeysToSet = new bytes32[](3); - bytes[] memory dataValuesToSet = new bytes[](3); - - // we are setting 3 x data key-value pairs for the same tokenid - tokenIdsToUpdate[0] = _TOKEN_ID_TO_SET; - tokenIdsToUpdate[1] = _TOKEN_ID_TO_SET; - tokenIdsToUpdate[2] = _TOKEN_ID_TO_SET; - - dataKeysToSet[0] = _LSP4_METADATA_KEY; - dataKeysToSet[1] = _NFT_ICON_DATA_KEY; - dataKeysToSet[2] = _NFT_MARKET_PLACE_URLS__DATA_KEY; - - dataValuesToSet[0] = lsp4MetadataValue; - dataValuesToSet[1] = nftIconValue; - dataValuesToSet[2] = nftMarketPlaceURLsValue; - - lsp8Contract.setDataBatchForTokenIds( - tokenIdsToUpdate, - dataKeysToSet, - dataValuesToSet - ); -} -``` - - - - - -```js -import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; - -const _NFT_ICON_DATA_KEY = keccak256('NFTIcon'); -const _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256('NFTMarketplaceURLs'); - -const _TOKEN_ID_TO_SET = - '0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe'; - -async function setMultipleDataForSingleTokenId( - lsp8Contract, - lsp4MetadataValue, - nftIconValue, - nftMarketPlaceURLsValue, -) { - const tokenIdsToUpdate = [ - _TOKEN_ID_TO_SET, - _TOKEN_ID_TO_SET, - _TOKEN_ID_TO_SET, - ]; - - const dataKeysToSet = [ - ERC725YDataKeys.LSP4.LSP4Metadata, - _NFT_ICON_DATA_KEY, - _NFT_MARKET_PLACE_URLS__DATA_KEY, - ]; - - const dataValuesToSet = [ - lsp4MetadataValue, - nftIconValue, - nftMarketPlaceURLsValue, - ]; - - await lsp8Contract.setDataBatchForTokenIds( - tokenIdsToUpdate, - dataKeysToSet, - dataValuesToSet, - ); -} -``` - - - - - -### Case 2: different tokenIds - -To set for instance the same data key-value pair (_e.g: `LSP4Metadata`_) for 3 x different `tokenId`s, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` will be as follow: - - - - - -```solidity -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.12; - -import { - ILSP8IdentifiableDigitalAsset as ILSP8 -} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol"; -import { - _LSP4_METADATA_KEY -} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; - -bytes32 constant _FIRST_TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe; -bytes32 constant _SECOND_TOKEN_ID_TO_SET = 0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef; -bytes32 constant _THIRD_TOKEN_ID_TO_SET = 0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d; - -function setMultipleDataForSingleTokenId( - ILSP8 lsp8Contract, - bytes memory firstTokenIdLsp4MetadataValue, - bytes memory secondTokenIdLsp4MetadataValue, - bytes memory thirdTokenIdLsp4MetadataValue -) { - bytes32[] memory tokenIdsToUpdate = new bytes32[](3); - bytes32[] memory dataKeysToSet = new bytes32[](3); - bytes[] memory dataValuesToSet = new bytes[](3); - - tokenIdsToUpdate[0] = _FIRST_TOKEN_ID_TO_SET; - tokenIdsToUpdate[1] = _SECOND_TOKEN_ID_TO_SET; - tokenIdsToUpdate[2] = _THIRD_TOKEN_ID_TO_SET; - - // we are setting the metadata for 3 x different tokenIds - dataKeysToSet[0] = _LSP4_METADATA_KEY; - dataKeysToSet[1] = _LSP4_METADATA_KEY; - dataKeysToSet[2] = _LSP4_METADATA_KEY; - - dataValuesToSet[0] = firstTokenIdLsp4MetadataValue; - dataValuesToSet[1] = secondTokenIdLsp4MetadataValue; - dataValuesToSet[2] = thirdTokenIdLsp4MetadataValue; - - lsp8Contract.setDataBatchForTokenIds( - tokenIdsToUpdate, - dataKeysToSet, - dataValuesToSet - ); -} -``` - - - - - -```js -import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; - -const _FIRST_TOKEN_ID_TO_SET = - '0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe'; -const _SECOND_TOKEN_ID_TO_SET = - '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef'; -const _THIRD_TOKEN_ID_TO_SET = - '0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d'; - -async function setMultipleDataForSingleTokenId( - lsp8Contract, - firstTokenIdLsp4MetadataValue, - secondTokenIdLsp4MetadataValue, - thirdTokenIdLsp4MetadataValue, -) { - const tokenIdsToUpdate = [ - _FIRST_TOKEN_ID_TO_SET, - _SECOND_TOKEN_ID_TO_SET, - _THIRD_TOKEN_ID_TO_SET, - ]; - - const dataKeysToSet = [ - ERC725YDataKeys.LSP4.LSP4Metadata, - ERC725YDataKeys.LSP4.LSP4Metadata, - ERC725YDataKeys.LSP4.LSP4Metadata, - ]; - - const dataValuesToSet = [ - firstTokenIdLsp4MetadataValue, - secondTokenIdLsp4MetadataValue, - thirdTokenIdLsp4MetadataValue, - ]; - - await lsp8Contract.setDataBatchForTokenIds( - tokenIdsToUpdate, - dataKeysToSet, - dataValuesToSet, - ); -} -``` - - - - - -## Checking if the Metadata of a tokenId changed - -Since LSP8 uses [ERC725Y](/standards/erc725#erc725y-generic-data-keyvalue-store) under the hood, the URI pointing to the metadata of a specific tokenId can be changed inside the ERC725Y storage of the LSP8 contract. - -We have seen in the previous section [**how to set metadata for one or multiple tokenIds**](#setting-metadata-for-one-or-multiple-tokenids). - -The two functions `setDataForTokenId(...)` and `setDataBatchForTokenIds(...)` emit a [`TokenIdDataChanged`](../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#tokeniddatachanged) event. You can listen for this event in the LSP8 contract from your dApp, filtering for the `LSP4Metadata` data key to check if the metadata of a tokenId has been changed. You can do so by filtering the first parameter with the `tokenId` and the second parameter with the [bytes32 value of the `LSP4Metadata` data key](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata). diff --git a/docs/contracts/overview/NFT/set-nft-metadata.md b/docs/contracts/overview/NFT/set-nft-metadata.md index cd49d6765..f8b8cead9 100644 --- a/docs/contracts/overview/NFT/set-nft-metadata.md +++ b/docs/contracts/overview/NFT/set-nft-metadata.md @@ -3,4 +3,227 @@ title: Set NFT Metadata sidebar_position: 3 --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # Set NFT Metadata + +The function [`setDataBatchForTokenIds(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatchfortokenids) can be used to set multiple [data key-value](/standards/erc725.md#erc725y-generic-data-keyvalue-store) pairs at once for one or multiple tokenIds. + +## Examples + +### Set multiple metadata at once on the same tokenId + +To set for instance 3 x data key-value pairs for the same `tokenId`, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` can be used as follow: + + + + + +```solidity +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.12; + +import { + ILSP8IdentifiableDigitalAsset as ILSP8 +} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol"; +import { + _LSP4_METADATA_KEY +} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; + +bytes32 constant _NFT_ICON_DATA_KEY = keccak256("NFTIcon"); +bytes32 constant _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256("NFTMarketplaceURLs"); + +bytes32 constant _TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe; + +function setMultipleDataForSingleTokenId( + ILSP8 lsp8Contract, + bytes memory lsp4MetadataValue, + bytes memory nftIconValue, + bytes memory nftMarketPlaceURLsValue +) { + bytes32[] memory tokenIdsToUpdate = new bytes32[](3); + bytes32[] memory dataKeysToSet = new bytes32[](3); + bytes[] memory dataValuesToSet = new bytes[](3); + + // we are setting 3 x data key-value pairs for the same tokenid + tokenIdsToUpdate[0] = _TOKEN_ID_TO_SET; + tokenIdsToUpdate[1] = _TOKEN_ID_TO_SET; + tokenIdsToUpdate[2] = _TOKEN_ID_TO_SET; + + dataKeysToSet[0] = _LSP4_METADATA_KEY; + dataKeysToSet[1] = _NFT_ICON_DATA_KEY; + dataKeysToSet[2] = _NFT_MARKET_PLACE_URLS__DATA_KEY; + + dataValuesToSet[0] = lsp4MetadataValue; + dataValuesToSet[1] = nftIconValue; + dataValuesToSet[2] = nftMarketPlaceURLsValue; + + lsp8Contract.setDataBatchForTokenIds( + tokenIdsToUpdate, + dataKeysToSet, + dataValuesToSet + ); +} +``` + + + + + +```js +import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; + +const _NFT_ICON_DATA_KEY = keccak256('NFTIcon'); +const _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256('NFTMarketplaceURLs'); + +const _TOKEN_ID_TO_SET = + '0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe'; + +async function setMultipleDataForSingleTokenId( + lsp8Contract, + lsp4MetadataValue, + nftIconValue, + nftMarketPlaceURLsValue, +) { + const tokenIdsToUpdate = [ + _TOKEN_ID_TO_SET, + _TOKEN_ID_TO_SET, + _TOKEN_ID_TO_SET, + ]; + + const dataKeysToSet = [ + ERC725YDataKeys.LSP4.LSP4Metadata, + _NFT_ICON_DATA_KEY, + _NFT_MARKET_PLACE_URLS__DATA_KEY, + ]; + + const dataValuesToSet = [ + lsp4MetadataValue, + nftIconValue, + nftMarketPlaceURLsValue, + ]; + + await lsp8Contract.setDataBatchForTokenIds( + tokenIdsToUpdate, + dataKeysToSet, + dataValuesToSet, + ); +} +``` + + + + + +### Set metadata on different tokenIds + +To set for instance the same data key-value pair (_e.g: `LSP4Metadata`_) for 3 x different `tokenId`s, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` can be used as follow: + + + + + +```solidity +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.12; + +import { + ILSP8IdentifiableDigitalAsset as ILSP8 +} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol"; +import { + _LSP4_METADATA_KEY +} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol"; + +bytes32 constant _FIRST_TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe; +bytes32 constant _SECOND_TOKEN_ID_TO_SET = 0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef; +bytes32 constant _THIRD_TOKEN_ID_TO_SET = 0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d; + +function setMultipleDataForSingleTokenId( + ILSP8 lsp8Contract, + bytes memory firstTokenIdLsp4MetadataValue, + bytes memory secondTokenIdLsp4MetadataValue, + bytes memory thirdTokenIdLsp4MetadataValue +) { + bytes32[] memory tokenIdsToUpdate = new bytes32[](3); + bytes32[] memory dataKeysToSet = new bytes32[](3); + bytes[] memory dataValuesToSet = new bytes[](3); + + tokenIdsToUpdate[0] = _FIRST_TOKEN_ID_TO_SET; + tokenIdsToUpdate[1] = _SECOND_TOKEN_ID_TO_SET; + tokenIdsToUpdate[2] = _THIRD_TOKEN_ID_TO_SET; + + // we are setting the metadata for 3 x different tokenIds + dataKeysToSet[0] = _LSP4_METADATA_KEY; + dataKeysToSet[1] = _LSP4_METADATA_KEY; + dataKeysToSet[2] = _LSP4_METADATA_KEY; + + dataValuesToSet[0] = firstTokenIdLsp4MetadataValue; + dataValuesToSet[1] = secondTokenIdLsp4MetadataValue; + dataValuesToSet[2] = thirdTokenIdLsp4MetadataValue; + + lsp8Contract.setDataBatchForTokenIds( + tokenIdsToUpdate, + dataKeysToSet, + dataValuesToSet + ); +} +``` + + + + + +```js +import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; + +const _FIRST_TOKEN_ID_TO_SET = + '0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe'; +const _SECOND_TOKEN_ID_TO_SET = + '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef'; +const _THIRD_TOKEN_ID_TO_SET = + '0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d'; + +async function setMultipleDataForSingleTokenId( + lsp8Contract, + firstTokenIdLsp4MetadataValue, + secondTokenIdLsp4MetadataValue, + thirdTokenIdLsp4MetadataValue, +) { + const tokenIdsToUpdate = [ + _FIRST_TOKEN_ID_TO_SET, + _SECOND_TOKEN_ID_TO_SET, + _THIRD_TOKEN_ID_TO_SET, + ]; + + const dataKeysToSet = [ + ERC725YDataKeys.LSP4.LSP4Metadata, + ERC725YDataKeys.LSP4.LSP4Metadata, + ERC725YDataKeys.LSP4.LSP4Metadata, + ]; + + const dataValuesToSet = [ + firstTokenIdLsp4MetadataValue, + secondTokenIdLsp4MetadataValue, + thirdTokenIdLsp4MetadataValue, + ]; + + await lsp8Contract.setDataBatchForTokenIds( + tokenIdsToUpdate, + dataKeysToSet, + dataValuesToSet, + ); +} +``` + + + + + +## Check if the metadata of a specific NFT (tokenId) has changed + +Since LSP8 uses [ERC725Y](/standards/erc725#erc725y-generic-data-keyvalue-store) under the hood, the URI pointing to the metadata of a specific tokenId can be changed inside the ERC725Y storage of the LSP8 contract. + +We have seen in the previous section [**how to set metadata for one or multiple tokenIds**](#setting-metadata-for-one-or-multiple-tokenids). + +The two functions `setDataForTokenId(...)` and `setDataBatchForTokenIds(...)` emit a [`TokenIdDataChanged`](../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#tokeniddatachanged) event. You can listen for this event in the LSP8 contract from your dApp, filtering for the `LSP4Metadata` data key to check if the metadata of a tokenId has been changed. You can do so by filtering the first parameter with the `tokenId` and the second parameter with the [bytes32 value of the `LSP4Metadata` data key](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata). diff --git a/docs/contracts/overview/Token/create-token.md b/docs/contracts/overview/Token/create-token.md index 097fad1fc..087b8da7e 100644 --- a/docs/contracts/overview/Token/create-token.md +++ b/docs/contracts/overview/Token/create-token.md @@ -73,7 +73,7 @@ contract MyToken is LSP7DigitalAsset { ## LSP7 Tokens extensions -The `@lukso/lsp7-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that enables to include functionalities for building your token through inheritance. +The `@lukso/lsp7-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that can be added through inheritance. This enables to include specific functionalities for building your token. | Extension contract | Description | | :----------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | diff --git a/docs/contracts/overview/Token/index.md b/docs/contracts/overview/Token/index.md index ade1a2eb8..938589115 100644 --- a/docs/contracts/overview/Token/index.md +++ b/docs/contracts/overview/Token/index.md @@ -20,7 +20,7 @@ The **LSP7DigitalAsset** contract represents digital assets for fungible tokens ## Installation & Usage -The LSP7 smart contracts and their ABIs are available are available as their own individual package. To use them, install `@lukso/lsp7-contracts` as a dependency in your project. +The LSP7 smart contracts and their ABIs are available are available in their own individual package. To use them, install `@lukso/lsp7-contracts` as a dependency in your project. @@ -46,7 +46,7 @@ pnpm add @lukso/lsp7-contracts -`LSP7DigitalAsset.sol` is an `abstract` contracts that is not deployable as is, because it does not contain any public functions by default to manage token supply (_e.g: no public `mint(...)` or `burn(...)` functions_). You can either: +`LSP7DigitalAsset.sol` is an `abstract` contract that is not deployable as is, because it does not contain any public functions by default to manage token supply (_e.g: no public `mint(...)` or `burn(...)` functions_). You can either: - the `LSP7Mintable` preset contract that contains a public `mint(...)` function callable only by the contract's owner. - or extend the `LSP7DigitalAsset` contract (_see below_) and create your own supply mechanism by defining public methods that use the internal `_mint(...)` and `_burn(...)` functions. diff --git a/docs/contracts/overview/Token/transfer-events.md b/docs/contracts/overview/Token/transfer-events.md deleted file mode 100644 index b59811b53..000000000 --- a/docs/contracts/overview/Token/transfer-events.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Listen for Transfer events -sidebar_position: 3 ---- - -# Listen for Transfer events