diff --git a/docs/learn/digital-assets/metadata-management/edit-token-metadata.md b/docs/learn/digital-assets/metadata-management/edit-token-metadata.md index ad8bd1da5..6f91b65db 100644 --- a/docs/learn/digital-assets/metadata-management/edit-token-metadata.md +++ b/docs/learn/digital-assets/metadata-management/edit-token-metadata.md @@ -9,9 +9,13 @@ import TabItem from '@theme/TabItem'; # Set LSP7 Token Metadata -In this guide, you will learn how to edit the [`LSP4Metadata`](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md) of an [LSP7 Digital Asset](../../../standards/tokens/LSP7-Digital-Asset.md). +> 👇🏻 Hands on 📽️ _ethers.js_ workshop video for the [**Oxford Blockchain Society**](https://x.com/oxfordblocksoc) from March 2024. -To edit an LSP7 Digital Asset metadata, you will need to: +
+ +
+ +In this guide, you will learn how to edit the [`LSP4Metadata`](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md) of an [LSP7 Digital Asset](../../../standards/tokens/LSP7-Digital-Asset.md). You will need to: 1. get your assets ready (images, videos, etc.) and create a metadata JSON file 2. upload these files using a preferred storage provider diff --git a/docs/learn/getting-started.mdx b/docs/learn/getting-started.mdx index e05c00931..e21b87281 100644 --- a/docs/learn/getting-started.mdx +++ b/docs/learn/getting-started.mdx @@ -29,43 +29,63 @@ export const CardData = [ ], }, { - image: ValidatorIcon, - imageTitle: 'Validator Icon', - cardHeading: 'Validators', + image: SmartContractDevIcon, + imageTitle: 'Smart Contract Developer Icon', + cardHeading: 'Smart Contract Developer', cardContent: [ { - linkText: 'Run a node for LUKSO', - linkPath: '../../networks/mainnet/running-a-node', + linkText: 'Get started with Tokens and NFTs', + linkPath: '../learn/digital-assets/getting-started', }, { - linkText: 'Become a Validator', - linkPath: '../../networks/mainnet/become-a-validator', + linkText: 'Create a token', + linkPath: '../learn/digital-assets/token/create-lsp7-token', }, { - linkText: 'Checkout the Network Parameters', - linkPath: '../../networks/mainnet/parameters', + linkText: 'Create an Automatic Token Forwarder for your UP', + linkPath: '../learn/universal-profile/universal-receiver/create-receiver-forwarder', }, ], }, { image: SmartContractDevIcon, - imageTitle: 'Smart Contract Developer Icon', - cardHeading: 'Smart Contract Developer', + imageTitle: 'Quickstart Integration', + cardHeading: 'Quickstart Integration', cardContent: [ { - linkText: 'Get started with Tokens and NFTs', - linkPath: '../learn/digital-assets/getting-started', + linkText: 'Migrate to LUKSO', + linkPath: '../learn/migrate/migrate-to-lukso', }, { - linkText: 'Create a token', - linkPath: '../learn/digital-assets/token/create-lsp7-token', + linkText: 'Refactor a Solidity ERC20 token to LSP7', + linkPath: '../learn/migrate/migrate-erc20-to-lsp7', }, { - linkText: 'Migrate ERC20 a token to LSP7', - linkPath: '../learn/migrate/migrate-erc20-to-lsp7', + linkText: 'Refactor a Solidity ERC721 NFT to LSP8', + linkPath: '../learn/migrate/migrate-erc721-to-lsp8', + }, + ], + }, + { + image: ValidatorIcon, + imageTitle: 'Validator Icon', + cardHeading: 'Validators', + cardContent: [ + { + linkText: 'Run a node for LUKSO', + linkPath: '../../networks/mainnet/running-a-node', + }, + { + linkText: 'Become a Validator', + linkPath: '../../networks/mainnet/become-a-validator', + }, + { + linkText: 'Checkout the Network Parameters', + linkPath: '../../networks/mainnet/parameters', }, ], }, + ]; # Quick Start diff --git a/docs/learn/migrate/migrate-erc20-to-lsp7.md b/docs/learn/migrate/migrate-erc20-to-lsp7.md index ba60a2227..85e1b38b0 100644 --- a/docs/learn/migrate/migrate-erc20-to-lsp7.md +++ b/docs/learn/migrate/migrate-erc20-to-lsp7.md @@ -4,21 +4,32 @@ sidebar_position: 2 description: Learn how to migrate your ERC20 token to the LSP7 Digital Asset standard on LUKSO. --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + import Erc20LSP7Table from '@site/src/components/Erc20LSP7Table'; # 🪙 Migrate ERC20 to LSP7 +> 👇🏻 Hands on 📽️ Solidity Workshop Video for the [**Oxford Blockchain Society**](https://x.com/oxfordblocksoc) from March 2024. + +
+ +
+ [LSP7DigitalAsset](../../standards/tokens/LSP7-Digital-Asset.md) is a new token standard that offers a wider range of functionality compared to [ERC20](https://eips.ethereum.org/EIPS/eip-20), as described in the [standard section](../../standards/tokens/LSP7-Digital-Asset.md). For migrating from ERC20 to LSP7, developers need to be aware of several key differences. -:::info +:::info Resources -If you need more details about the interface differences between ERC20 and LSP7, please visit our [contract overview](../../contracts/overview/DigitalAssets#comparisons-with-erc20--erc721) page. +See the [contract overview](../../contracts/overview/DigitalAssets#comparisons-with-erc20--erc721) page for the interface differences between ERC20 and LSP7. ::: -## Smart Contract Building +## Comparisons -Usually, to create an ERC20 token, `ERC20` is imported from [@openzeppelin/contracts](https://www.npmjs.com/package/@openzeppelin/contracts) package, and inherited. +### Solidity code + +Usually, to create an ERC20 token, we import and inherit the `ERC20` contract from the [@openzeppelin/contracts](https://www.npmjs.com/package/@openzeppelin/contracts) package. ```solidity title="ERC20 Token" // SPDX-License-Identifier: MIT @@ -33,9 +44,12 @@ contract MyERC20Token is ERC20 { } ``` -To create an LSP7 token, `LSP7` is imported from [@lukso/lsp7-contracts](https://www.npmjs.com/package/@lukso/lsp7-contracts) package, and inherited. +To create an LSP7 token, we should instead import `LSP7DigitalAsset` from the [`@lukso/lsp7-contracts`](https://www.npmjs.com/package/@lukso/lsp7-contracts) package, and replace it in the inheritance. + +To deploy an `LSP7DigitalAsset` we can use the same [`constructor`](../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md#constructor) parameters. but we also need to specify 2 extra parameters (_explanations of params provided in the code comments below_). -The constructor arguments definitions can be found explained in the [constructor API](../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md#constructor) section. +- the `lsp4TokenType`. +- if the token `isNonDivisible`. ```solidity title="LSP7 Token" // SPDX-License-Identifier: Apache-2.0 @@ -43,12 +57,15 @@ pragma solidity ^0.8.15; import "@lukso/lsp7-contracts/contracts/LSP7DigitalAsset.sol"; +// highlight-next-line contract MyLSP7Token is LSP7DigitalAsset { constructor( string memory name, // Name of the token string memory symbol, // Symbol of the token address tokenOwner, // Owner able to add extensions and change metadata + // highlight-next-line uint256 lsp4tokenType, // 0 if representing a fungible token, 1 if representing an NFT + // highlight-next-line bool isNonDivisible // false for decimals equal to 18, true for decimals equal to 0 ) LSP7DigitalAsset(name, symbol, tokenOwner, lsp4tokenType, isNonDivisible) { // _mint(to, amount, force, data) @@ -59,21 +76,65 @@ contract MyLSP7Token is LSP7DigitalAsset { } ``` -## Behavior +### Functions & Behaviors Below are the function signatures of the transfer functions for ERC20 and LSP7, respectively. -ERC20: `function transferFrom(address from, address to, uint256 amount);` +
+ +
+ +**ERC20** + +```solidity +function transferFrom( + address from, + address to, + uint256 amount +) external; +``` + +
+ +
+ +**LSP7** + +```solidity +function transfer( + address from, + address to, + uint256 amount, + // highlight-next-line + bool force, + // highlight-next-line + bytes data +) external; +``` + +
+ +
+ +There are 3 main differences for LSP7 to note + +- **Additional `force` parameter**: for the [`mint(...)`](../../contracts/contracts/LSP7DigitalAsset/presets/LSP7Mintable.md#mint) and [`transfer(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#ransfer) functions. + +For full compatibility with ERC20 behavior (where the recipient can be any address), set this to `true`. Setting it to `false` will only allow the transfer to smart contract addresses supporting the [**LSP1UniversalReceiver** interfaceId](../../contracts/interface-ids.md). + +> See the [**LSP7 Standard > `force` mint and transfer**](../../standards/tokens/LSP7-Digital-Asset.md#lsp1-token-hooks#force-mint-and-transfer) section for more details. -LSP7: `function transfer(address from, address to, uint256 amount, bool force, bytes data);` +- **Additional `data` field**: for the `mint(...)`, `transfer(...)`, and [`burn(...)`](../../contracts/contracts/LSP7DigitalAsset/extensions/LSP7Burnable.md#burn) functions. -- For LSP7, **mint and transfer functions will have a `force` additional field**. For full compatibility with ERC20 behavior (where the recipient can be any address), set this to `true`. Setting it to `false` will only allow the transfer to smart contract addresses supporting the LSP1 interfaceId. (Check [LSP1UniversalReceiver section](../../standards/tokens/LSP7-Digital-Asset.md#lsp1-token-hooks) in LSP7DigitalAsset for more info). +For full compatibility with ERC20 behavior, set this to empty bytes `""`. This data is only relevant when the recipient is a smart contract that supports the LSP1 interfaceId, where the data will be sent and the recipient can act on it (_e.g., reject the transfer, forward the tokens to a vault, etc..._). -- For LSP7, **mint, transfer, and burn functions will have `data` as an additional field**. For full compatibility with ERC20 behavior, set this to empty bytes. This data will only be relevant when the recipient is a smart contract address supporting the LSP1 interfaceId (Check [LSP1UniversalReceiver section](../../standards/tokens/LSP7-Digital-Asset.md#lsp1-token-hooks) in LSP7DigitalAsset for more info), where the data will be sent and the recipient can act on it (e.g., reject the transfer, forward the tokens to a vault, etc.). +> See the [**LSP7 Standard > LSP1 Token Hooks**](../../standards/tokens/LSP7-Digital-Asset.md#lsp1-token-hooks) section for more details. -- **LSP7 metadata is generic**, in contrast to ERC20 where the metadata is limited to name and symbol. The [generic key-value store](../../standards/lsp-background/erc725.md#erc725y-generic-data-keyvalue-store) in LSP7 allows for storing any possible data. +- **LSP7 metadata is generic**: via a [flexible data key / value store](<(../../standards/lsp-background/erc725.md#erc725y-generic-data-keyvalue-store)>). It can be set and retrieved via [`setData(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#setdata) / [`setDataBatch(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#setdatabatch) and [`getData(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#getdata) / [`getDataBatch(...)`](../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#getdatabatch). -## Interacting with Contracts +ERC20 metadata is limited to `name()` and `symbol()`. LSP7 allows to store any data after deployment without limitations. + +### Interact with the Token Contract :::info @@ -81,11 +142,11 @@ To check function definitions and explanations of behavior and each parameter, c ::: -To interact with LSP7DigitalAsset contract, different functions should be called. This is a table comparing function definitions: +To interact with the LSP7DigitalAsset contract, different functions should be called. This is a table comparing the different function definitions: -## dApps and Indexers +### Events :::info @@ -93,32 +154,51 @@ To check event definitions and explanations of behavior and each parameter, chec ::: -The table below shows the different event definitions that should be used to track activity on an LSP7-DigitalAsset contract. +Services like dApps and Indexers can use different events from LSP7 to listen to activities. The table below shows the different event definitions that should be used to track activity on an LSP7-DigitalAsset contract. -| ERC20 Event | LSP7 Event | -| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `Transfer(address indexed from, address indexed to, uint256 value)` | `Transfer(address indexed operator, address indexed from, address indexed to, uint256 amount, bool force, bytes data)` | -| `Approval(address indexed owner, address indexed spender, uint256 value)` | `OperatorAuthorizationChanged(address indexed operator, address indexed tokenOwner, uint256 indexed amount, bytes operatorNotificationData)` | -| _No equivalent_ | `OperatorRevoked(address indexed operator, address indexed tokenOwner, bool indexed notified, bytes operatorNotificationData)` | +| ERC20 Event | LSP7 Event | +| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +|
Transfer(
address indexed from,
address indexed to,
uint256 value
);
|
Transfer(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bool force,
bytes data
)
| +|
Approval(
address indexed owner,
address indexed spender,
uint256 value
)
|
OperatorAuthorizationChanged(
address indexed operator,
address indexed tokenOwner,
uint256 indexed amount,
bytes operatorNotificationData
);
| +| _No equivalent_ |
OperatorRevoked(
address indexed operator,
address indexed tokenOwner,
bool indexed notified,
bytes operatorNotificationData
)
| ## Metadata Management ### Basic Token Information -In ERC20, the name and symbol of a token can be retrieved by calling their own function: +
+ +
+ +**ERC20** ```javascript -// ERC20 const name = await token.name(); const symbol = await token.symbol(); ``` -In LSP7, the token name and symbol can be retrieved with [getData](../../contracts/contracts/ERC725/ERC725.md#getdata) function, since LSP7 uses a generic metadata key value store: +
+ +
+ +**How to retrieve?** + +In ERC20, the name and symbol of a token can be retrieved by calling their own function. + +
+
+ +
+ +
+ +**LSP7** ```javascript -// LSP7 -const nameKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4TokenName')); -const symbolKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4TokenSymbol')); +import { keccak256, toUtf8Bytes } from 'ethers'; + +const nameKey = keccak256(toUtf8Bytes('LSP4TokenName')); +const symbolKey = keccak256(toUtf8Bytes('LSP4TokenSymbol')); const nameValue = await token.getData(nameKey); const symbolValue = await token.getData(symbolKey); @@ -127,15 +207,105 @@ const name = ethers.toUtf8String(nameValue); const symbol = ethers.toUtf8String(symbolValue); ``` +
+ +
+ +**How to retrieve?** + +In LSP7, the token name and symbol can be retrieved with [`getData(bytes32)`](../../contracts/contracts/ERC725/ERC725.md#getdata). They are stored in the generic metadata key-value store under the data keys [`LSP4TokenName`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokenname) and [`LSP4TokenSymbol`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokensymbol). + +Once you have fetched the raw hex encoded value, you will need to decode it into a human readable string. + +
+
+ +You can import the list of data keys related to each individual LSP standard from one of our library. There are 2 options: + + + + + +For dApp developers, you can import the data keys from the `@lukso/lsp-smart-contracts` and use them directly in your scripts via _ethers.js_ or _web3.js_. + +```javascript +import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; + +const nameKey = ERC725YDataKeys.LSP4.LSP4TokenName; +const symbolKey = ERC725YDataKeys.LSP4.LSP4TokenSymbol; + +const nameValue = await token.getData(nameKey); // 0x555020417374726f20373235 +const symbolValue = await token.getData(symbolKey); // 0x5550373235 + +const name = ethers.toUtf8String(nameValue); // UP Astro 725 +const symbol = ethers.toUtf8String(symbolValue); // UP725 +``` + + + + + +You can also obtain the full schema with all the definitions from our [`@erc725/erc725.js`](../../tools/erc725js/getting-started.md) library. **This library will also help you to [encode easily](../../tools/erc725js/methods.md#encodedata) data key value pairs.** + +You can also import the [full schema definition](../../tools/erc725js/schemas.md) of the LSP4 Metadata from `@erc725/erc725.js`. The library can also provide convenience for fetching, encoding and decoding. + + + +```javascript title="Example of decoding using the LSP4 schema and erc725.js" +import { ERC725 } from '@erc725/erc725.js'; +import LSP4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAssetMetadata.json'; + +const nameKey = LSP4Schema.find((schema) => schema.name == 'LSP4TokenName').key; +const symbolKey = LSP4Schema.find((schema) => schema.name == 'LSP4TokenSymbol').key; + +const nameValue = await token.getData(nameKey); // 0x555020417374726f20373235 +const symbolValue = await token.getData(symbolKey); // 0x5550373235 + +const [name, symbol] = ERC725.decodeData([ + { + keyName: 'LSP4TokenName', + value: nameValue, + }, + { + keyName: 'LSP4TokenSymbol', + value: symbolValue, + }, +]); +/** +[ + { + name: 'LSP4TokenName', + key: '0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1', + value: "UP Astro 725", + }, + { + name: 'LSP4TokenSymbol', + key: '0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756', + value: "UP725", + }, +] +*/ +``` + + + + + + + ### Extended Token Metadata -:::info +:::success Tutorial 🎥 -To learn more about setting and creating the LSP4Metadata JSON, check the [metadata](../digital-assets/metadata-management/metadata-preparation.md) section. +See the [**Metadata Management**](../digital-assets/metadata-management/edit-token-metadata.md) guide + video for how to create and set the JSON metadata for your LSP7 Token. ::: -LSP7 allows for more flexible and extensive metadata storage. You can store a JSON object containing additional token information: +LSP7 allows for more flexible and extensible metadata. The [`LSP4Metadata`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) is a JSON object that can contain many information about the token, including: + +- 🌐 **official link to websites** (_e.g: project website, social medias, community channels, etc..._). +- 🖼️ **images** (token icon and backgrounds) to display the token in dApps, explorers, or decentralised exchanges. +- 🏷️ **custom attributes** (can be displayed as badges on UIs). ```javascript const metadataKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4Metadata')); diff --git a/docs/learn/migrate/migrate-erc721-to-lsp8.md b/docs/learn/migrate/migrate-erc721-to-lsp8.md index 58fbb05b1..1fff31f5f 100644 --- a/docs/learn/migrate/migrate-erc721-to-lsp8.md +++ b/docs/learn/migrate/migrate-erc721-to-lsp8.md @@ -1,24 +1,35 @@ --- -sidebar_label: '🌅 ERC721 to LSP8' +sidebar_label: '🖼️ ERC721 to LSP8' sidebar_position: 3 description: Learn how to migrate your ERC721 token to the LSP8 Identifiable Digital Asset standard on LUKSO. --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + import Erc721LSP8Table from '@site/src/components/Erc721LSP8Table'; # 🖼️ Migrate ERC721 to LSP8 +> 👇🏻 Hands on 📽️ Solidity Workshop Video for the [**Oxford Blockchain Society**](https://x.com/oxfordblocksoc) from March 2024. + +
+ +
+ [LSP8IdentifiableDigitalAsset](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) is a new token standard that offers a wider range of functionality compared to [ERC721](https://eips.ethereum.org/EIPS/eip-721), as described in the [standard section](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md). For migrating from ERC721 to LSP8, developers need to be aware of several key differences. -:::info +:::info Resources -If you need more details about the interface differences between ERC721 and LSP8, please visit our [contract overview](../../contracts/overview/DigitalAssets#comparisons-with-erc20--erc721) page. +See the [contract overview](../../contracts/overview/DigitalAssets#comparisons-with-erc20--erc721) page for the interface differences between ERC721 and LSP8. ::: -## Smart Contract Building +## Comparisons + +### Solidity code -Usually, to create an ERC721 token, `ERC721` is imported from [@openzeppelin/contracts](https://www.npmjs.com/package/@openzeppelin/contracts) package, and inherited. +Usually, to create an ERC721 token, we import and inherit the `ERC721` contract from the [@openzeppelin/contracts](https://www.npmjs.com/package/@openzeppelin/contracts) package. ```solidity title="ERC721 Token" // SPDX-License-Identifier: MIT @@ -33,48 +44,97 @@ contract MyERC721Token is ERC721 { } ``` -To create an LSP8 NFT, `LSP8` is imported from [@lukso/lsp8-contracts](https://www.npmjs.com/package/@lukso/lsp8-contracts) package, and inherited. +To create an LSP8 token, we should instead import `LSP8IdentifiableDigitalAsset` from the [`@lukso/lsp8-contracts`](https://www.npmjs.com/package/@lukso/lsp8-contracts) package, and replace it in the inheritance. + +To deploy an `LSP8IdentifiableDigitalAsset` we can use the same [`constructor`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md#constructor) parameters, but we also need to specify 2 extra parameters (_explanations of params provided in the code comments below_). -The constructor arguments definitions can be found explained in the [constructor API](../../contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md#constructor) section. +- the `lsp4TokenType_`. +- the `lsp8TokenIdFormat_`. -```js +```solidity title="LSP8 Token" // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.15; import "@lukso/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol"; +// highlight-next-line contract MyLSP8Token is LSP8IdentifiableDigitalAsset { constructor( string memory name, // Name of the token string memory symbol, // Symbol of the token address tokenOwner, // Owner able to add extensions and change metadata - uint256 lsp4TokenType_, // 1 if representing an NFT, 2 if representing an advanced collection of multiple NFTs + // highlight-next-line + uint256 lsp4TokenType_, // 1 if NFT, 2 if an advanced collection of multiple NFTs + // highlight-next-line uint256 lsp8TokenIdFormat_ // 0 for compatibility with ERC721, check LSP8 specs for other values ) LSP8IdentifiableDigitalAsset(name, symbol, tokenOwner, lsp4TokenType_, lsp8TokenIdFormat_) { - // Your constructor logic - bytes32 tokenId = bytes32(uint256(1)); - _mint(tokenOwner, tokenId, true, ""); + // _mint(to, tokenId, force, data) + // force: should be set to true to allow EOA to receive tokens + // data: only relevant if the `to` is a smart contract supporting LSP1. + _mint(tokenOwner, bytes32(uint256(1)), true, ""); } } ``` -## Behavior - -- For LSP8, the tokenId is represented as `bytes32` in contrast with ERC721 where its represented as `uint256`. This design decision allow for more representation of tokenIds. +### Functions & Behaviors Below are the function signatures of the transfer functions for ERC721 and LSP8, respectively. -ERC721: `function transferFrom(address from, address to, uint256 tokenId);` +
+ +
+ +**ERC721** + +```solidity +function transferFrom( + address from, + address to, + uint256 tokenId +) external; +``` + +
+ +
+ +**LSP8** + +```solidity +function transfer( + address from, + address to, + bytes32 tokenId, + // highlight-next-line + bool force, + // highlight-next-line + bytes data +) external; +``` + +
+ +
+ +There are 4 main differences for LSP8 to note: + +- **TokenId representation**: In LSP8, the `tokenId` is represented as `bytes32` instead of `uint256` in ERC721. This allows for more flexible token identification schemes. + +- **Additional `force` parameter**: for the [`mint(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/presets/LSP8Mintable.md#mint) and [`transfer(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#transfer) functions. + +For full compatibility with ERC721 behavior (where the recipient can be any address), set this to `true`. Setting it to `false` will only allow the transfer to smart contract addresses supporting the [**LSP1UniversalReceiver** interfaceId](../../contracts/interface-ids.md). + +> See the [**LSP8 Standard > `force` mint and transfer**](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp1-token-hooks#force-mint-and-transfer) section for more details. -LSP8: `function transfer(address from, address to, bytes32 tokenId, bool force, bytes data);` +- **Additional `data` field**: for the `mint(...)`, `transfer(...)`, and [`burn(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md#burn) functions. -- For LSP8, **mint and transfer functions will have a `force` additional field**. For full compatibility with ERC721 behavior (where the recipient can be any address), set this to `true`. Setting it to `false` will only allow the transfer to smart contract addresses supporting the LSP1 interfaceId. (Check [LSP1UniversalReceiver section](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp1-token-hooks) in LSP8IdentifiableDigitalAsset for more info). +For full compatibility with ERC721 behavior, set this to empty bytes `""`. This data is only relevant when the recipient is a smart contract that supports the LSP1 interfaceId, where the data will be sent and the recipient can act on it (_e.g., reject the transfer, forward the tokens to a vault, etc..._). -- For LSP8, **mint, transfer, and burn functions will have `data` as an additional field**. For full compatibility with ERC721 behavior, set this to empty bytes. This data will only be relevant when the recipient is a smart contract address supporting the LSP1 interfaceId (Check [LSP1UniversalReceiver section](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp1-token-hooks)in LSP8IdentifiableDigitalAsset for more info), where the data will be sent and the recipient can act on it (e.g., reject the transfer, forward the tokens to a vault, etc.). +> See the [**LSP8 Standard > LSP1 Token Hooks**](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp1-token-hooks) section for more details. -- **LSP8 metadata is generic**, in contrast to ERC721 where the metadata is limited to name and symbol and tokenURI. The [generic key-value store](../../standards/lsp-background/erc725.md#erc725y-generic-data-keyvalue-store) in LSP8 allows for storing any possible data. +- **LSP8 metadata is generic**: via a [flexible data key / value store](<(../../standards/lsp-background/erc725.md#erc725y-generic-data-keyvalue-store)>). It can be set and retrieved via [`setData(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdata) / [`setDataBatch(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatch) and [`getData(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#getdata) / [`getDataBatch(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#getdatabatch). -## Interacting with Contracts +### Interact with the Token Contract :::info @@ -82,46 +142,65 @@ To check function definitions and explanations of behavior and each parameter, c ::: -To interact with LSP8IdentifiableDigitalAsset contract, different functions should be called. This is a table comparing function definitions: +To interact with the LSP8IdentifiableDigitalAsset contract, different functions should be called. This is a table comparing the different function definitions: -## dApps and Indexers +### Events :::info -To check event definitions and explanations of behavior and each parameter, check [API Reference](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md) section. +To check event definitions and explanations of behavior and each parameter, check [API Reference](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#events) section. ::: -The table below shows the different event definitions that should be used to track activity on an LSP8-IdentifiableDigitalAsset contract. +Services like dApps and Indexers can use different events from LSP8 to listen to activities. The table below shows the different event definitions that should be used to track activity on an LSP8-IdentifiableDigitalAsset contract. -| ERC721 Event | LSP8 Event | -| ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| `Transfer(address indexed from, address indexed to, uint256 indexed tokenId)` | `Transfer(address operator, address indexed from, address indexed to, bytes32 indexed tokenId, bool force, bytes data)` | -| `Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)` | `OperatorAuthorizationChanged(address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bytes operatorNotificationData)` | -| `ApprovalForAll(address indexed owner, address indexed operator, bool approved)` | _No direct equivalent_ | -| _No equivalent_ | `OperatorRevoked(address indexed operator, address indexed tokenOwner, bytes32 indexed tokenId, bool notified, bytes operatorNotificationData)` | +| ERC721 Event | LSP8 Event | +| ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|
Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
|
Transfer(
address operator,
address indexed from,
address indexed to,
bytes32 indexed tokenId,
bool force,
bytes data
)
| +|
Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
)
|
OperatorAuthorizationChanged(
address indexed operator,
address indexed tokenOwner,
bytes32 indexed tokenId,
bytes operatorNotificationData
);
| +|
ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
)
| _No direct equivalent_ | +| _No equivalent_ |
OperatorRevoked(
address indexed operator,
address indexed tokenOwner,
bytes32 indexed tokenId,
bool notified,
bytes operatorNotificationData
)
| ## Metadata Management ### Basic Token Information -In ERC721, the name, symbol and the tokenURI of a tokenId can be retrieved by calling their own function: +
+ +
+ +**ERC721** ```javascript -// ERC721 const name = await token.name(); const symbol = await token.symbol(); const tokenURI = await token.tokenURI(tokenId); ``` -In LSP8, the token name and symbol can be retrieved with [getData](../../contracts/contracts/ERC725/ERC725.md#getdata) function, since LSP8 uses a generic metadata key value store: +
+ +
+ +**How to retrieve?** + +In ERC721, the name, symbol, and tokenURI of a token can be retrieved by calling their own functions. + +
+
+ +
+ +
+ +**LSP8** ```javascript -// LSP8 -const nameKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4TokenName')); -const symbolKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4TokenSymbol')); +import { keccak256, toUtf8Bytes } from 'ethers'; + +const nameKey = keccak256(toUtf8Bytes('LSP4TokenName')); +const symbolKey = keccak256(toUtf8Bytes('LSP4TokenSymbol')); const nameValue = await token.getData(nameKey); const symbolValue = await token.getData(symbolKey); @@ -130,19 +209,108 @@ const name = ethers.toUtf8String(nameValue); const symbol = ethers.toUtf8String(symbolValue); ``` -### Extended Token Metadata +
-:::info +
+ +**How to retrieve?** -To learn more about setting and creating the LSP4Metadata JSON, check the [metadata](../digital-assets/metadata-management/metadata-preparation.md) section. +In LSP8, the token name, symbol and base URI can be retrieved with [`getData(bytes32)`](../../contracts/contracts/ERC725/ERC725.md#getdata). They are stored in the generic metadata key-value store under the data keys [`LSP4TokenName`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokenname), [`LSP4TokenSymbol`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokensymbol) and [`LSP8TokenMetadataBaseURI`](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-8-IdentifiableDigitalAsset.md#lsp8tokenmetadatabaseuri). + +Once you have fetched the raw hex encoded value, you will need to decode it into a human readable string. + +
+
+ +You can import the list of data keys related to each individual LSP standard from one of our library. There are 2 options: + + + + + +For dApp developers, you can import the data keys from the `@lukso/lsp-smart-contracts` and use them directly in your scripts via _ethers.js_ or _web3.js_. + +```javascript +import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts'; + +const nameKey = ERC725YDataKeys.LSP4.LSP4TokenName; +const symbolKey = ERC725YDataKeys.LSP4.LSP4TokenSymbol; + +const nameValue = await token.getData(nameKey); // 0x4c5350382050726f66696c65 +const symbolValue = await token.getData(symbolKey); // 0x4c5350382050726f66696c65 + +const name = ethers.toUtf8String(nameValue); // Cool NFT +const symbol = ethers.toUtf8String(symbolValue); // COOL +``` + + + + + +You can also obtain the [full schema definition](../../tools/erc725js/schemas.md) of the LSP4 Metadata from [`@erc725/erc725.js`](../../tools/erc725js/getting-started.md) library. **This library will also help you to [encode easily](../../tools/erc725js/methods.md#encodedata) data key value pairs.** + +```javascript +import { ERC725 } from '@erc725/erc725.js'; +import LSP4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAssetMetadata.json'; + +const nameKey = LSP4Schema.find((schema) => schema.name == 'LSP4TokenName').key; +const symbolKey = LSP4Schema.find( + (schema) => schema.name == 'LSP4TokenSymbol', +).key; + +const nameValue = await token.getData(nameKey); // 0x4c5350382050726f66696c65 +const symbolValue = await token.getData(symbolKey); // 0x4c5350382050726f66696c65 + +const [name, symbol] = ERC725.decodeData([ + { + keyName: 'LSP4TokenName', + value: nameValue, + }, + { + keyName: 'LSP4TokenSymbol', + value: symbolValue, + }, +]); +/** +[ + { + name: 'LSP4TokenName', + key: '0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1', + value: "Cool NFT", + }, + { + name: 'LSP4TokenSymbol', + key: '0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756', + value: "COOL", + }, +] +*/ +``` + + + + + +### Extended Collection Metadata + +:::success Tutorial 🎥 + +See the [**Metadata Management**](../digital-assets/metadata-management/edit-token-metadata.md) guide + video for how to create and set the JSON metadata for your LSP8 Token. ::: -LSP8 allows for more flexible and extensive metadata storage directly on-chain. You can store a JSON object containing information about the whole NFT contract and for each individual tokenId. +[LSP8 allows for more flexible and extensible metadata](../../standards/tokens/LSP8-Identifiable-Digital-Asset.md#lsp8-collection-vs-tokenid-metadata). You can store a JSON object containing information about: + +- the whole NFT Collection contract +- and for each individual NFT `tokenId`. -#### For the NFT contract +The [`LSP4Metadata`](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata) is a JSON object that can contain many information about the token, including: -```js +- 🌐 **official link to websites** (_e.g: project website, social medias, community channels, etc..._). +- 🖼️ **images** (token icon and backgrounds) to display the token in dApps, explorers, or decentralised exchanges. +- 🏷️ **custom attributes** (for each specific NFTs for instance, can be displayed as badges on UIs). + +```javascript const metadataKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4Metadata')); const storedMetadata = await token.getData(metadataKey); const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); @@ -151,22 +319,37 @@ const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); { LSP4Metadata: { - description: 'A unique digital artwork.', + description: 'A unique digital artwork collection.', links: [ - { title: 'Artist Website', url: 'https://artist.com' }, - { title: 'Gallery', url: 'https://gallery.com/artwork' } + { title: 'Website', url: 'https://myawesomenft.com' }, + { title: 'Twitter', url: 'https://twitter.com/myawesomenft' } ], - images: [ + icon: [ { - width: 1024, - height: 1024, - url: 'ipfs://QmW4wM4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', + width: 256, + height: 256, + url: 'ipfs://QmW5cF4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', verification: { method: 'keccak256(bytes)', - data: '0xa9399df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6e', + data: '0x01299df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6f', } } ], + images: [ + [ + { + width: 1024, + height: 974, + url: 'ipfs://QmW4wM4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', + verification: { + method: 'keccak256(bytes)', + data: '0xa9399df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6e', + } + }, + // ... more image sizes + ], + // ... more images + ], assets: [{ verification: { method: 'keccak256(bytes)', @@ -182,12 +365,12 @@ const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); type: "string" }, { - key: 'Year', - value: 2023, + key: 'Edition', + value: 1, type: "number" }, { - key: 'Unique', + key: 'Original', value: true, type: "boolean" } @@ -196,58 +379,41 @@ const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); } ``` -#### For each individual tokenId +### NFT-specific Metadata -```js +LSP8 allows you to set and retrieve metadata for individual tokens using the [`setDataForTokenId(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatafortokenid) and [`getDataForTokenId(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#getdatafortokenid) functions. This is particularly useful for NFTs where each token might have unique properties. +```javascript +// Setting token-specific metadata +const tokenId = '0x1234...'; // your token ID in bytes32 format const metadataKey = ethers.keccak256(ethers.toUtf8Bytes('LSP4Metadata')); -const storedMetadata = await token.getDataForTokenId(metadataKey); +const metadataValue = ethers.toUtf8Bytes(JSON.stringify({ + // Your token-specific metadata here +})); + +await token.setDataForTokenId(tokenId, metadataKey, metadataValue); + +// Retrieving token-specific metadata +const storedMetadata = await token.getDataForTokenId(tokenId, metadataKey); const retrievedJsonMetadata = JSON.parse(ethers.toUtf8String(storedMetadata)); -// JSON Stored: +// Example of token-specific metadata { LSP4Metadata: { - description: 'A unique digital artwork.', - links: [ - { title: 'Artist Website', url: 'https://artist.com' }, - { title: 'Gallery', url: 'https://gallery.com/artwork' } - ], - images: [ - { - width: 1024, - height: 1024, - url: 'ipfs://QmW4wM4r9yWeY1gUCtt7c6v3ve7Fzdg8CKvTS96NU9Uiwr', - verification: { - method: 'keccak256(bytes)', - data: '0xa9399df007997de92a820c6c2ec1cb2d3f5aa5fc1adf294157de563eba39bb6e', - } - } - ], - assets: [{ - verification: { - method: 'keccak256(bytes)', - data: '0x98fe032f81c43426fbcfb21c780c879667a08e2a65e8ae38027d4d61cdfe6f55', - }, - url: 'ipfs://QmPJESHbVkPtSaHntNVY5F6JDLW8v69M2d6khXEYGUMn7N', - fileType: 'json' - }], + description: 'Unique NFT #1234', + image: 'ipfs://QmYourImageCID', attributes: [ { - key: 'Artist', - value: 'Jane Doe', - type: "string" + trait_type: 'Rarity', + value: 'Legendary' }, { - key: 'Year', - value: 2023, - type: "number" - }, - { - key: 'Unique', - value: true, - type: "boolean" + trait_type: 'Power Level', + value: 9000 } ] } } ``` + +This feature allows for much more flexible and dynamic NFTs compared to the static `tokenURI` approach in ERC721. diff --git a/docs/learn/universal-profile/universal-receiver/create-receiver-forwarder.md b/docs/learn/universal-profile/universal-receiver/create-receiver-forwarder.md index 50757679c..7ef594e6c 100644 --- a/docs/learn/universal-profile/universal-receiver/create-receiver-forwarder.md +++ b/docs/learn/universal-profile/universal-receiver/create-receiver-forwarder.md @@ -1,5 +1,5 @@ --- -sidebar_label: 'Create a LSP1 Forwarder' +sidebar_label: 'Create a Token Forwarder' sidebar_position: 2 description: This smart contract tutorial guides you on how to create a LSP1 Delegate contract that forwards portion of received tokens automatically to any address. --- @@ -7,7 +7,7 @@ description: This smart contract tutorial guides you on how to create a LSP1 Del import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Create a LSP1 Forwarder +# Create a Token Forwarder This guide will teach you how to create a basic custom [Universal Receiver Delegate](../../../standards/generic-standards/lsp1-universal-receiver-delegate.md) contract for the following use-case: diff --git a/src/components/Erc20LSP7Table/index.js b/src/components/Erc20LSP7Table/index.js index f32d3828a..897b2aa5b 100644 --- a/src/components/Erc20LSP7Table/index.js +++ b/src/components/Erc20LSP7Table/index.js @@ -2,7 +2,7 @@ import React from 'react'; export default function Erc20LSP7Table() { return ( - +
@@ -12,78 +12,105 @@ export default function Erc20LSP7Table() { @@ -91,11 +118,17 @@ export default function Erc20LSP7Table() { No equivalent @@ -103,13 +136,19 @@ export default function Erc20LSP7Table() { No equivalent @@ -117,49 +156,114 @@ export default function Erc20LSP7Table() { No equivalent + + + + @@ -167,7 +271,20 @@ export default function Erc20LSP7Table() { No equivalent diff --git a/src/components/Erc721LSP8Table/index.js b/src/components/Erc721LSP8Table/index.js index f87f5b19b..507f85c99 100644 --- a/src/components/Erc721LSP8Table/index.js +++ b/src/components/Erc721LSP8Table/index.js @@ -2,7 +2,7 @@ import React from 'react'; export default function Erc721LSP8Table() { return ( -
ERC20 Function
- name() +
name()
- getData(bytes32 dataKey) with
{' '} - dataKey = keccak256('LSP4TokenName') +
+              const dataKey = keccak256('LSP4TokenName')
+              
+ getData(bytes32 dataKey) +
- symbol() +
symbol()
- getData(bytes32 dataKey) with
{' '} - dataKey = keccak256('LSP4TokenSymbol') +
+              const dataKey = keccak256('LSP4TokenSymbol')
+              
+ getData(bytes32 dataKey) +
- decimals() +
decimals()
- decimals() +
decimals()
- totalSupply() +
totalSupply()
- totalSupply() +
totalSupply()
- balanceOf(address account) +
balanceOf(address account)
- balanceOf(address account) +
balanceOf(address account)
- approve(address spender, uint256 amount) +
+              allowance(address owner, address spender)
+            
- - authorizeOperator(address spender, +
+              authorizedAmountFor(
               
- uint256 amount, + {' '} address spender,
- bytes memory data) -
+ {' '} address owner +
) +
- allowance(address owner, address spender) + No equivalent - - authorizedAmountFor(address spender, -
- address owner) -
+
getOperatorsOf(address owner)
- No equivalent +
+              approve(address spender, uint256 amount)
+            
- getOperatorsOf(address owner) +
+              authorizeOperator(
+              
+ {' '}address spender, +
+ {' '}uint256 amount, +
+ {' '}bytes memory data +
+ ); +
+ + 🔍 Function details + +
+ + 🔀 Example Transaction +
- - revokeOperator(address spender, +
+              revokeOperator(
+              
+ {' '}address spender,
- bytes memory data) -
+ {' '}bytes memory data +
) +
+ + 🔍 Function details +
- - increaseAllowance(address spender, +
+              increaseAllowance(
               
- uint256 addedAmount, + {' '}address spender,
- bytes memory data) -
+ {' '}uint256 addedAmount, +
+ {' '}bytes memory data +
) +
+ + 🔍 Function details +
- - decreaseAllowance(address spender, +
+              decreaseAllowance(
+              
+ {' '}address spender,
- uint256 subtractedAmount, + {' '}uint256 subtractedAmount,
- bytes memory data) -
+ {' '}bytes memory data +
) +
+ + 🔍 Function details +
- transfer(address to, uint256 amount) +
transfer(address to, uint256 amount)
- - transfer(address from, +
+              transfer(
+              
+ {' '}address from,
- address to, + {' '}address to,
- uint256 amount, + {' '}uint256 amount,
- bool force + {' '}bool force
- bytes memory data) -
+ {' '}bytes memory data +
) +
+

+ Pass the msg.sender address as from{' '} + parameter. +

+ + 🔍 Function details +
- transferFrom(address from, address to, uint256 amount) +
+              transferFrom(
+              
+ {' '}address from, +
+ {' '} address to, +
+ {' '} uint256 amount +
+ {' '}) +
- - transfer(address from, +
+              transfer(
               
- address to, + {' '}address from,
- uint256 amount, + {' '}address to,
- bool force + {' '}uint256 amount, +
+ {' '}bool force +
+ {' '}bytes memory data +
) +
+

+ Use msg.sender as an operator and use a different{' '} + from address to transfer tokens from. +

+ + 🔍 Function details + +
+ No equivalent + +
+              function transferBatch(
+              
{' '} address[] from, +
{' '} address[] to, +
{' '} uint256[] amount, +
{' '} bool[] force, +
{' '} bytes[] data
- bytes memory data) - + ); +
+

+ Transfer the same token to multiple recipients in a single + transaction.{' '} + + + See our examples code snippets. + + +

+ + 🔍 Function details +
- batchCalls(bytes[] memory data) +
batchCalls(bytes[] memory data)
+

+ Allows to pass multiple calls into a single transaction. For + instance: +

    +
  1. Transfer tokens to an address.
  2. +
  3. Authorize an operator.
  4. +
  5. Update the token contract metadata.
  6. +
  7. etc...
  8. +
+ + 🔍 Function details + +

+
@@ -12,63 +12,80 @@ export default function Erc721LSP8Table() { @@ -131,15 +187,21 @@ export default function Erc721LSP8Table() { No equivalent @@ -147,7 +209,25 @@ export default function Erc721LSP8Table() { No equivalent diff --git a/src/css/custom.css b/src/css/custom.css index 568975039..2f3c25df9 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -34,6 +34,13 @@ --ifm-alert-padding-horizontal: 1.2rem; --ifm-navbar-padding-vertical: calc(var(--ifm-spacing-vertical) * 0.2); --ifm-navbar-padding-horizontal: calc(var(--ifm-spacing-horizontal) * 0.5); + /* snippets */ + --docusaurus-highlighted-code-line-bg: rgba(161, 243, 153, 0.261); + /* If you have a different syntax highlighting theme for dark mode. */ + [data-theme='dark'] { + /* Color which works with dark mode syntax highlighting theme */ + --docusaurus-highlighted-code-line-bg: rgba(161, 243, 153, 0.261); + } } .markdown { @@ -260,6 +267,19 @@ table.lsp-features td { margin-right: 1em; } +.tab_javascript[aria-selected='true'] { + border-bottom-color: #f1dd30; +} +.tab_javascript { + color: #1e1e1e; +} +.tab_javascript:before { + content: url('/static/img/learn/javascript-logo.png'); + position: relative; /*or absolute*/ + z-index: 100000; /*a number that's more than the modal box*/ + margin-right: 1em; +} + #guides-links li { list-style-type: '\1f517' !important; } @@ -285,3 +305,21 @@ div.cardwithimage { #token-nft-combinations td { text-align: center; } + +table#erc20-to-lsp7-table pre { + margin-bottom: 1rem; + margin-top: 1rem; +} + +table#erc20-to-lsp7-table tr { + background-color: transparent; +} + +table#erc721-to-lsp8-table pre { + margin-bottom: 1rem; + margin-top: 1rem; +} + +table#erc721-to-lsp8-table tr { + background-color: transparent; +} diff --git a/static/img/learn/javascript-logo.png b/static/img/learn/javascript-logo.png new file mode 100644 index 000000000..ff27bd2f8 Binary files /dev/null and b/static/img/learn/javascript-logo.png differ
ERC721 Function
- name() +
name()
- getData(bytes32 dataKey) with
{' '} - dataKey = keccak256('LSP4TokenName') +
+              const dataKey = keccak256('LSP4TokenName')
+              
+ getData(bytes32 dataKey) +
- symbol() +
symbol()
- getData(bytes32 dataKey) with
{' '} - dataKey = keccak256('LSP4TokenSymbol') +
+              const dataKey = keccak256('LSP4TokenSymbol')
+              
+ getData(bytes32 dataKey) +
- balanceOf(address owner) +
balanceOf(address owner)
- balanceOf(address tokenOwner) +
balanceOf(address tokenOwner)
- ownerOf(uint256 tokenId) +
ownerOf(uint256 tokenId)
- tokenOwnerOf(bytes32 tokenId) +
tokenOwnerOf(bytes32 tokenId)
- approve(address to, uint256 tokenId) +
approve(address to, uint256 tokenId)
- - authorizeOperator(address operator, +
+              authorizeOperator(
               
- bytes32 tokenId, + {' '}address operator,
- bytes memory data) -
+ {' '}bytes32 tokenId, +
+ {' '}bytes memory data +
) +
+ + 🔍 Function details +
- getApproved(uint256 tokenId) +
getApproved(uint256 tokenId)
- getOperatorsOf(bytes32 tokenId) +
getOperatorsOf(bytes32 tokenId)
+ + 🔍 Function details +
- setApprovalForAll(address operator, bool approved) +
+              setApprovalForAll(address operator, bool approved)
+            
@@ -78,52 +95,91 @@ export default function Erc721LSP8Table() {
- isApprovedForAll(address owner, address operator) +
+              isApprovedForAll(address owner, address operator)
+            
- - isOperatorFor(address operator, +
+              isOperatorFor(
+              
+ {' '}address operator,
- bytes32 tokenId) -
+ {' '}bytes32 tokenId +
) +
+ + 🔍 Function details +
- transferFrom(address from, address to, uint256 tokenId) +
+              transferFrom(
+              
+ {' '}address from, +
+ {' '}address to, +
+ {' '}uint256 tokenId +
) +
- - transfer(address from, +
+              transfer(
               
- address to, + {' '}address from,
- bytes32 tokenId, + {' '}address to,
- bool force, + {' '}bytes32 tokenId,
- bytes memory data) -
+ {' '}bool force, +
+ {' '}bytes memory data +
) +
+ + 🔍 Function details +
- - safeTransferFrom(address from, address to, uint256 tokenId) - +
+              safeTransferFrom(
+              
+ {' '}address from, +
+ {' '}address to, +
+ {' '}uint256 tokenId +
) +
- - transfer(address from, +
+              transfer(
+              
+ {' '}address from,
- address to, + {' '}address to,
- bytes32 tokenId, + {' '}bytes32 tokenId,
- bool force, + {' '}bool force,
- bytes memory data) -
+ {' '}bytes memory data +
) +
+

+ Set force = false for safe transfer behavior +

+ + 🔍 Function details +
- - revokeOperator(address operator, +
+              revokeOperator(
+              
+ {' '}address operator,
- bytes32 tokenId, + {' '}bytes32 tokenId,
- bool notify, + {' '}bool notify,
- bytes memory data) -
+ {' '}bytes memory data +
) +
+ + 🔍 Function details +
- batchCalls(bytes[] memory data) +
batchCalls(bytes[] memory data)
+

+ Allows to pass multiple calls into a single transaction. For + instance: +

    +
  1. Transfer an NFT to an address.
  2. +
  3. + Authorize an operator for a specific tokenId. +
  4. +
  5. Update the NFT metadata.
  6. +
  7. etc...
  8. +
+

+ + 🔍 Function details + + {/*
  • + 🔀 Example Transaction +
  • */}