diff --git a/docs/learn/universal-profile/img/transfer-lsp7-tokens.png b/docs/learn/universal-profile/img/transfer-lsp7-tokens.png deleted file mode 100644 index 74df361f0a..0000000000 Binary files a/docs/learn/universal-profile/img/transfer-lsp7-tokens.png and /dev/null differ diff --git a/docs/learn/universal-profile/img/transfer-tokens-and-nfts.png b/docs/learn/universal-profile/img/transfer-tokens-and-nfts.png new file mode 100644 index 0000000000..9c17121302 Binary files /dev/null and b/docs/learn/universal-profile/img/transfer-tokens-and-nfts.png differ diff --git a/docs/learn/universal-profile/interactions/transfer-lsp7-token.md b/docs/learn/universal-profile/interactions/transfer-lsp7-token.md deleted file mode 100644 index f399bf43fd..0000000000 --- a/docs/learn/universal-profile/interactions/transfer-lsp7-token.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -sidebar_label: 'Transfer LSP7 Token' -sidebar_position: 2 -description: Learn how to transfer LSP7 tokens from a Universal Profile to any address on the LUKSO Blockchain, using the UP Browser Extension. ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Transfer LSP7 Token - -
- Transfering 1,000 CHILL tokens between two Universal Profiles -
-Transfering 1,000 CHILL tokens between two Universal Profiles. -

-
- -:::info - -The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/tree/main/digital-assets). - -::: - -This guide will teach you how to transfer an existing [LSP7 Digital Asset](../../../standards/tokens/LSP7-Digital-Asset.md) across [Universal Profiles](../../../standards/accounts/lsp0-erc725account.md). - -## Setup Dependencies - -The following code snippets require the installation of the following libraries: - -- [`ethers.js`](https://github.com/ethers-io/ethers.js/) or [`web3.js`](https://www.npmjs.com/package/web3) -- [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) - - - - -```shell -npm install ethers @lukso/lsp-smart-contracts -``` - - - - -```shell -npm install web3 @lukso/lsp-smart-contracts -``` - - - - -## Code Examples - -Create an instance of your Universal Profile and the LSP7 Token you want to transfer. - -You will need: - -- the `address` of the 🆙 obtained from the guide **Login to UP**) and LSP7 Token contract. -- use the `UniversalProfile` and `LSP7DigitalAsset` ABIs imported from the `@lukso/lsp-smart-contracts` library - -After setting up the contracts, you can set up the parameters for the LSP7 token [`transfer(...)`](https://docs.lukso.tech/contracts/contracts/LSP7DigitalAsset/#transfer) function. - - - - -```js -import { ethers } from 'ethers'; - -// Import smart contract ABI -import LSP7Mintable from '@lukso/lsp-smart-contracts/artifacts/LSP7Mintable.json'; - -const provider = new ethers.BrowserProvider(window.lukso); - -await provider.send('eth_requestAccounts', []); - -const signer = await provider.getSigner(); - -const myToken = new ethers.Contract( - '0xF860E9B7fC187D58132216849f1f5DBfd02fcb8C', // Token contract address - LSP7Mintable.abi, -); - -await myToken.transfer( - signer.getAddress(), // sender address - '0x48AC443777DC66798510f687cf0b449721195Ea9', // recipient's address (EOA or contract) - 15, // amount of tokens - true, // force flag, false to only allow contract with a Universal Receiver, true for any address - '0x', // any additional data to send alongside the transfer -); -``` - - - - -```js -import Web3 from 'web3'; - -// Import schemas and ABI -import LSP7Mintable from '@lukso/lsp-smart-contracts/artifacts/LSP7Mintable.json'; - -const web3 = new Web3(window.lukso); - -await web3.eth.requestAccounts(); -const accounts = await web3.eth.getAccounts(); - -// Instantiate the token with an address -const myToken = new web3.eth.Contract(LSP7Mintable.abi, '0x...'); - -await myToken.methods - .transfer( - accounts[0], // sender address - '0x...', // receiving address - 15, // token amount - false, // force parameter - '0x', // additional data - ) - .send({ from: accounts[0] }); -``` - - - - diff --git a/docs/learn/universal-profile/interactions/transfer-tokens-and-nfts.md b/docs/learn/universal-profile/interactions/transfer-tokens-and-nfts.md new file mode 100644 index 0000000000..02c44b9e70 --- /dev/null +++ b/docs/learn/universal-profile/interactions/transfer-tokens-and-nfts.md @@ -0,0 +1,233 @@ +--- +sidebar_label: 'Transfer Tokens & NFTs' +sidebar_position: 2 +description: Learn how to transfer LSP7 tokens and LSP8 individual NFT tokenIds from a Universal Profile to any address on the LUKSO Blockchain, using the UP Browser Extension. +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Transfer Tokens & NFTs + +
+ Transfering 1,000 CHILL tokens or a Chillwhale NFT between two Universal Profiles +
+Transfering 1,000 CHILL tokens between two Universal Profiles. +

+
+ +:::info + +The full code of this example can be found in the 👾 [lukso-playground](https://github.com/lukso-network/lukso-playground/tree/main/digital-assets). + +::: + +This guide will teach you how to transfer [LSP7 tokens](../../../standards/tokens/LSP7-Digital-Asset.md) or [LSP8 NFTs](../../../standards/tokens/LSP8-Identifiable-Digital-Asset.md) from a [Universal Profile](../../../standards/accounts/lsp0-erc725account.md) to any address. + +## Setup Dependencies + +You will need the following libraries to do this tutorial: + +- [`ethers.js`](https://github.com/ethers-io/ethers.js/) or [`web3.js`](https://www.npmjs.com/package/web3) +- [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts/) + + + + +```shell +npm install ethers @lukso/lsp-smart-contracts +``` + + + + +```shell +npm install web3 @lukso/lsp-smart-contracts +``` + + + + +## Examples + +First, create an instance of the LSP7 or LSP8 contract. You will need: + +- the `address` of the LSP7 or LSP8 Token contract you want to transfer tokens / NFT from. +- one of the following smart contract ABI from the `@lukso/lsp-smart-contracts` package: + - `LSP7DigitalAsset` if you want to transfer tokens. + - `LSP8IdentifiableDigitalAsset` if you want to transfer an NFT from the collection. + +### Transfer LSP7 tokens + +Call the [LSP7 `transfer(address,address,uint256,bool,bytes)`](../../../contracts/contracts/LSP7DigitalAsset/#transfer) function and pass the amount as 3rd parameter. + +> Since most tokens have 18 [`decimals()`](../../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#decimals), make sure to specify the `amount` with 18 decimals place. For instance, if you want to transfer 8 tokens the `amount` parameter will be: `8_000_000_000_000_000_000` ✅, not `8` ❌. + +> Otherwise, the transfer might have occured but you might not see the balance of the recipient updated, since you transferred only a tiny small amount (`8` for a token with 18 decimals is basically 1 / 1e18). To do so easily, use one of number utility function from _ethers.js_ or _web3.js_. + + + + +```js +import { ethers } from 'ethers'; + +// Import the LSP7 ABI +import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; + +// Connect to the UP Browser extension +const provider = new ethers.BrowserProvider(window.lukso); +await provider.send('eth_requestAccounts', []); +const signer = await provider.getSigner(); + +// Create instance of the CHILL token contract +const chillToken = new ethers.Contract( + '0x5b8b0e44d4719f8a328470dccd3746bfc73d6b14', // Chillwhale Token contract address + LSP7DigitalAsset.abi, +); + +await chillToken.transfer( + signer.getAddress(), // (from) sender address (= our Universal Profile) + '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address + ethers.parseUnits('15', 18), // (amount) of tokens to transfer (CHILL have 18 decimals) + true, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) + '0x', // (data) any additional data to send alongside the transfer +); +``` + + + + +```js +import Web3 from 'web3'; + +// Import the LSP7 ABI +import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'; + +// Connect to the UP Browser extension +const web3 = new Web3(window.lukso); +await web3.eth.requestAccounts(); +const accounts = await web3.eth.getAccounts(); + +// Create instance of the CHILL token contract +const chillToken = new web3.eth.Contract( + LSP7DigitalAsset.abi, + '0x5b8b0e44d4719f8a328470dccd3746bfc73d6b14', // Chillwhale Token contract address +); + +await chillToken.methods + .transfer( + accounts[0], // (from) sender address (= our Universal Profile) + '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address + web3.utils.toWei('15'), // (amount) of tokens to transfer (CHILL have 18 decimals) + false, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) + '0x', // (data) any additional data to send alongside the transfer + ) + .send({ from: accounts[0] }); +``` + + + + + +:::info Notes on decimals + +If you are transferring LSP7 tokens with `0` as [`decimals()`](../../../contracts/contracts/LSP7DigitalAsset/LSP7DigitalAsset.md#decimals) or NFTs represented as LSP7 with [TokenType 1](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4tokentype), just pass the amount as a number without using the number formatting function. + +Here is an example to transfer 2 x digital trading cards from the **LUKSO Family Game** (series LFG03): + +```ts +// Create instance of the LUKSO Family Game (LFG03) token contract +const luksoFamilyGameSeries03 = new ethers.Contract( + '0x6a58a1f2cbb5b39d90618736a7730bff0fa72801', // LUKSO Family Game (LFG03) contract address + LSP7DigitalAsset.abi, +); + +await luksoFamilyGameSeries03.transfer( + signer.getAddress(), // (from) sender address (= our Universal Profile) + '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address + 2, // (amount) of tokens to transfer (LFG03 token contract has 0 decimals) + true, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) + '0x', // (data) any additional data to send alongside the transfer +); +``` + +::: + +### Transfer LSP8 NFTs + +Call the [LSP8 `transfer(address,address,bytes32,bool,bytes)`](../../../contracts/contracts/LSP8IdentifiableDigitalAsset/#transfer) function and pass the `tokenId` of the NFT from the collection you want to transfer as 3rd parameter. + +Make sure you specify the **_tokenId_ as a 32 bytes long value**, as shown in the code snippet below. + + + + +```js +import { ethers } from 'ethers'; + +// Import the LSP8 ABI +import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; + +// Connect to the UP Browser extension +const provider = new ethers.BrowserProvider(window.lukso); +await provider.send('eth_requestAccounts', []); +const signer = await provider.getSigner(); + +// Create instance of the Chillwhale NFT collection contract +const chillwhaleNft = new ethers.Contract( + '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT collection contract address + LSP8IdentifiableDigitalAsset.abi, +); + +// Create the bytes32 representation of the tokenId number 319 (2nd param right pad to 32 bytes) +const tokenId = ethers.toBeHex(319, 32); + +await chillwhaleNft.transfer( + signer.getAddress(), // (from) sender address (= our Universal Profile) + '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address + tokenId, // (tokenId) of the NFT to transfer + true, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) + '0x', // (data) any additional data to send alongside the transfer +); +``` + + + + +```js +import Web3 from 'web3'; + +// Import the LSP8 ABI +import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; + +// Connect to the UP Browser extension +const web3 = new Web3(window.lukso); +await web3.eth.requestAccounts(); +const accounts = await web3.eth.getAccounts(); + +// Create instance of the Chillwhale NFT collection contract +const chillwhaleNft = new web3.eth.Contract( + LSP8IdentifiableDigitalAsset.abi, + '0x86e817172b5c07f7036bf8aa46e2db9063743a83', // Chillwhale NFT collection contract address +); + +// Create the bytes32 representation of the tokenId number 319 (2nd param right pad to 32 bytes - web3.js expect to specify in character counts, not bytes) +const tokenId = web3.utils.padLeft(319, 64); + +await chillwhaleNft.methods + .transfer( + accounts[0], // (from) sender address (= our Universal Profile) + '0x02e655F92f01BC7880807ec409F134b91bb28381', // (to) recipient's address + tokenId, // (tokenId) of the NFT to transfer + false, // (force) flag, false to only allow contract with a Universal Receiver, true for any address (EOA or any contract) + '0x', // (data) any additional data to send alongside the transfer + ) + .send({ from: accounts[0] }); +``` + + + + diff --git a/docusaurus.config.js b/docusaurus.config.js index 327d0a2519..bb14528516 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -96,8 +96,8 @@ export default { }, // Learn/Universal Profile { - from: '/learn/universal-profile/transfer-lsp7-token', - to: '/learn/universal-profile/interactions/transfer-lsp7-token', + from: '/learn/universal-profile/interactions/transfer-lsp7-token', + to: '/learn/universal-profile/interactions/transfer-tokens-and-nfts', }, { from: '/learn/universal-profile/transfer-lyx', diff --git a/package.json b/package.json index 8ad7fe1df4..2138d80b3c 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "prettier:fix": "prettier \"src/**/*.js\" \"docs/**/*.md\" --write" }, "dependencies": { - "@cookbookdev/docsbot": "^4.21.9", + "@cookbookdev/docsbot": "^4.21.23", "@docusaurus/core": "latest", "@docusaurus/plugin-client-redirects": "latest", "@docusaurus/plugin-google-gtag": "latest", diff --git a/yarn.lock b/yarn.lock index d5aa1a3070..230a72e1cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1723,10 +1723,11 @@ __metadata: languageName: node linkType: hard -"@cookbookdev/docsbot@npm:^4.21.9": - version: 4.21.9 - resolution: "@cookbookdev/docsbot@npm:4.21.9" +"@cookbookdev/docsbot@npm:^4.21.23": + version: 4.21.23 + resolution: "@cookbookdev/docsbot@npm:4.21.23" dependencies: + "@cookbookdev/sonner": 1.5.1 "@headlessui/react": ^1.7.18 "@headlessui/tailwindcss": ^0.2.0 "@monaco-editor/react": ^4.6.0 @@ -1760,7 +1761,7 @@ __metadata: framer-motion: ^6.5.1 idb: ^8.0.0 jszip: ^3.10.1 - nanoid: ^5.0.5 + nanoid: 3.3.7 posthog-js: ^1.136.8 prop-types: ^15.8.1 react-complex-tree: ^2.3.7 @@ -1772,7 +1773,6 @@ __metadata: remark-parse: ^11.0.0 remark-rehype: ^11.1.0 solc: ^0.8.25 - sonner: ^1.4.41 styled-components: ^6.1.8 swr: ^2.2.5 tailwind-merge: ^2.2.1 @@ -1782,7 +1782,17 @@ __metadata: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 - checksum: a6bd6ed9213392212a73405bf7160fbd8e323121975ed7aac5bf96d9f081843926aa28054e23bb7288cc0f3359556fa8179704875be12e8ac7f6489d27d6230e + checksum: 18b0665f073a26cf96af1abb3e68a717c3527290b207b1a22107f2fe9d690eb111fd57b1b6b1cc700f63397a512b0ac68f32cdcf0812aaa513996cb65c6455ea + languageName: node + linkType: hard + +"@cookbookdev/sonner@npm:1.5.1": + version: 1.5.1 + resolution: "@cookbookdev/sonner@npm:1.5.1" + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 658774d5055f47e1ccb64f97e9affc149bba6042b15318cd861ce790550041c9a3c96605b773a7853e32af0980d37eabd6db1077d0b2a103495ea9d025d4ff4e languageName: node linkType: hard @@ -10477,7 +10487,7 @@ __metadata: version: 0.0.0-use.local resolution: "lukso-docs@workspace:." dependencies: - "@cookbookdev/docsbot": ^4.21.9 + "@cookbookdev/docsbot": ^4.21.23 "@docusaurus/core": latest "@docusaurus/module-type-aliases": latest "@docusaurus/plugin-client-redirects": latest @@ -11946,7 +11956,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.7": +"nanoid@npm:3.3.7, nanoid@npm:^3.3.7": version: 3.3.7 resolution: "nanoid@npm:3.3.7" bin: @@ -11955,15 +11965,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^5.0.5": - version: 5.0.7 - resolution: "nanoid@npm:5.0.7" - bin: - nanoid: bin/nanoid.js - checksum: 25ab0b0cf9082ae6747f0f55cec930e6c1cc5975103aa3a5fda44be5720eff57d9b25a8a9850274bfdde8def964b49bf03def71c6aa7ad1cba32787819b79f60 - languageName: node - linkType: hard - "negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" @@ -14573,16 +14574,6 @@ __metadata: languageName: node linkType: hard -"sonner@npm:^1.4.41": - version: 1.5.0 - resolution: "sonner@npm:1.5.0" - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - checksum: 0b0f911785b74209a44fe85fe5b0cf3bd440c78271285026dc1290bb6e8c6296c92a01a0f72646d18312654c138838aeadd15a55c20954a193cb65ccf84f51e3 - languageName: node - linkType: hard - "sort-css-media-queries@npm:2.2.0": version: 2.2.0 resolution: "sort-css-media-queries@npm:2.2.0"