From 876a02e0a605b62825e78532674ce58064d0a3fc Mon Sep 17 00:00:00 2001 From: Felix Hildebrandt Date: Fri, 16 Feb 2024 15:50:37 +0100 Subject: [PATCH 1/6] Add metadata encoding / decoding --- digital-assets/encode-metadata.ts | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 digital-assets/encode-metadata.ts diff --git a/digital-assets/encode-metadata.ts b/digital-assets/encode-metadata.ts new file mode 100644 index 0000000..e14caef --- /dev/null +++ b/digital-assets/encode-metadata.ts @@ -0,0 +1,82 @@ +import { ERC725 } from '@erc725/erc725.js'; +import LSP4DigitalAssetSchema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; +import { EncodeDataInput } from '@erc725/erc725.js/build/main/src/types/decodeData'; + +const LSP4SampleJSON = { + LSP4Metadata: { + name: 'CHILL', + description: 'introducing $chill', + links: [ + { + title: 'X', + url: 'https://twitter.com/chillwhales', + }, + { + title: 'Common Ground', + url: 'https://app.cg/c/bZe26yK9Uh/', + }, + { + title: 'Chillwhales', + url: 'https://chillwhales.com/', + }, + ], + icon: [ + { + width: 1614, + height: 1614, + url: 'ipfs://bafkreigiidxipuk3y5ep5jygsfcs5pdqtfjhkges7hlpimt3mqksznoeyu', + verification: { + method: 'keccak256(bytes)', + data: '0x583d661aed68417e9fd1500f629c8d9cd6fadd9c31e948b2a6870b66c4f3bc03', + }, + }, + ], + images: [ + [ + { + width: 480, + height: 480, + url: 'ipfs://bafybeihejctjezrjiid3ed4aw5dq3vxlwqfvigdu77ucpszgtmitlza5ty', + verification: { + method: 'keccak256(bytes)', + data: '0xd1ee7a4fe6d0a05f2929a8e47a68f1828d0145d113567a432391becf2ba83cbf', + }, + }, + ], + ], + backgroundImage: [ + { + width: 1200, + height: 400, + url: 'ipfs://bafybeiglmtsb7k7bhchfxphazb6lqln45uaox3lqvx557dk5he5wqxqp2i', + verification: { + method: 'keccak256(bytes)', + data: '0xd22f654e7dee3971ff32220b8c91ddd3427842392087a9bcae8d218915859eee', + }, + }, + ], + assets: [], + }, +}; + +const lsp4SampleMetadata: EncodeDataInput[] = [ + { + keyName: 'LSP4Metadata', + value: { + json: LSP4SampleJSON, + url: 'ipfs://QmQTqheBLZFnQUxu5RDs8tA9JtkxfZqMBcmGd9sukXxwRm', // replace with example IPFS url + }, + }, +]; + +// Encode the new LSP4 metadata as Verifiable URI +// https://docs.lukso.tech/tools/erc725js/classes/ERC725#encodedata +const encodedLSP4Metadata = ERC725.encodeData(lsp4SampleMetadata, LSP4DigitalAssetSchema); +console.log(encodedLSP4Metadata); + +const decodedLSP4Metadata = ERC725.decodeData( + [{ keyName: encodedLSP4Metadata.keys[0], value: encodedLSP4Metadata.values[0] }], + LSP4DigitalAssetSchema, +); + +console.log(JSON.stringify(decodedLSP4Metadata, undefined, 2)); From b8e690b70e79352909f03f2596613cc328644691 Mon Sep 17 00:00:00 2001 From: CJ42 Date: Fri, 16 Feb 2024 18:32:57 +0000 Subject: [PATCH 2/6] feat: create backend guide to register LSP12 Issued Assets Co-authored-by: Magali Morin --- package.json | 3 +- universal-profile/register-asset-backend.ts | 66 +++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 universal-profile/register-asset-backend.ts diff --git a/package.json b/package.json index 9e68671..a92a049 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ }, "homepage": "https://github.com/lukso-network/lukso-playground#readme", "scripts": { - "lint": "eslint . --ext .ts,.js" + "lint": "eslint . --ext .ts,.js", + "lint:fix": "eslint . --ext .ts,.js --fix" }, "devDependencies": { "@erc725/erc725.js": "^0.23.0", diff --git a/universal-profile/register-asset-backend.ts b/universal-profile/register-asset-backend.ts new file mode 100644 index 0000000..09cf244 --- /dev/null +++ b/universal-profile/register-asset-backend.ts @@ -0,0 +1,66 @@ +import { ethers } from 'ethers'; + +import { ERC725 } from '@erc725/erc725.js'; +import LSP12Schema from '@erc725/erc725.js/schemas/LSP12IssuedAssets.json'; + +import UniversalProfileArtifact from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; +import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; + +// We will register the issued assets by setting the following LSP12 data keys +// - LSP12IssuedAssets[] +// - LSP12IssuedAssetsMap: + +// add the type of asset (LSP7 or LSP8) and their address in the object list below +const issuedAssets = [ + { + interfaceId: INTERFACE_IDS.LSP7DigitalAsset, + address: '0xf7056bdE90f494F55967858F1e9E4AFB1026C5C8', + }, + { + interfaceId: INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + address: '0xf651b88925C0B6C81Ad6f658a2F104226d837F60', + }, + // { + // interfaceId: LSP7 or LSP8 interface ID (or other), + // address: '0xasset-address', + // }, +]; + +// setup: get the private key of your main controller behind the Universal Profile extension +// or any controller that has access to the Universal Profile +const UNIVERSAL_PROFILE_ADDRESS = '0x9fc7e5095A054dfA3c6b237E0e5d686638394248'; +const PRIVATE_KEY = '0x...'; +const RPC_ENDPOINT = 'https://rpc.testnet.lukso.network'; + +const provider = new ethers.JsonRpcProvider(RPC_ENDPOINT); +const myWallet = new ethers.Wallet(PRIVATE_KEY, provider); + +// 1. encode the data keys related to LSP12IssuedAssets[] +const erc725 = new ERC725(LSP12Schema, UNIVERSAL_PROFILE_ADDRESS, RPC_ENDPOINT, { + ipfsGateway: 'https://api.universalprofile.cloud/ipfs', +}); + +const allAssetAddresses = issuedAssets.map((asset) => asset.address); + +const issuedAssetsMap = issuedAssets.map((asset, index) => { + return { + keyName: 'LSP12IssuedAssetsMap:
', + dynamicKeyParts: asset.address, + value: [asset.interfaceId, ERC725.encodeValueType('uint128', index)], + }; +}); + +const { keys: lsp12DataKeys, values: lsp12Values } = erc725.encodeData([ + { keyName: 'LSP12IssuedAssets[]', value: allAssetAddresses }, + ...issuedAssetsMap, +]); + +// 2. create an instance of your Universal Profile contract +const myUPContract = new ethers.Contract( + UNIVERSAL_PROFILE_ADDRESS, + UniversalProfileArtifact.abi, + myWallet, +); + +// 3. set these data keys created at step 1. using `setDataBatch` on the UP address +await myUPContract.setDataBatch(lsp12DataKeys, lsp12Values); From 69dfdc92d5edf655104960d9b08977db9e7cabef Mon Sep 17 00:00:00 2001 From: Felix Hildebrandt Date: Mon, 19 Feb 2024 18:22:25 +0100 Subject: [PATCH 3/6] add CONTRIBUTING.md --- CONTRIBUTING.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8dce5bf --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# 💁‍♂️ Contributing to LUKSO Playground + +We're thrilled you're interested in contributing to the LUKSO Playground! This space is dedicated to providing developers with code snippets and tools for interacting with LUKSO standards efficiently. + +## Getting Started + +1. Create a fork of this repository. +2. Clone your repository to make changes. +3. Follow the installation within the [README.md](./README.md) + +## Making Changes + +1. **Create a separate branch**: For each new feature, docs, or fix, create a new branch in your fork like the following structure: `feature/feature-name` or `fix/issue-fix`, `docs/added-content`. The naming helps organize your contributions and separates them from your main branch. +2. **Commit your changes**: After running `npm run build` and applying styles using `prettier`, you can commit your local changes to your branch. Please ensure that changes are regularly pulled from the `main` branch of the original repository to stay up-to-date and avoid conflicts. +3. **Submit a pull request**: Once your changes are ready and tested, you can push the latest changes to your GitHub fork and `submit a pull request` to this repository. Please provide a clear and detailed explanation of the changes and why they are needed. Include any relevant `issue numbers`. +4. **Review Process**: The project maintainers will review your pull request. Be open to feedback and be prepared to make further changes if requested. Once approved, a maintainer will `merge` your changes into the `main` branch. + +## Contribution Guidelines + +To ensure a smooth contribution process for everyone, please follow these guidelines: + +- **Maintain Generality**: This repository is designed as a generic foundation for developers to start building with LSPs efficiently. Contributions should not introduce features too specific or outside of the LSP ecosystem. +- **Follow Code Styles**: Follow the coding conventions used throughout the project, including indentation, naming conventions, and comments. +- **Build and Test**: Ensure your code does not break the existing functionality. Add tests for any new features or fixes when possible. Any upcoming features should not break existing scripts or contracts. +- **Create Documentation**: Add or update any relevant documentation with your changes, especially if adding new features. + +## Report Bugs + +If you've found issues within contracts or scripts, please [open a new issue](https://github.com/lukso-network/lukso-playground/issues). From 39c0ac79d02c44b1a2827b39f708a9d9c567b4b1 Mon Sep 17 00:00:00 2001 From: Felix Hildebrandt Date: Tue, 20 Feb 2024 12:00:30 +0100 Subject: [PATCH 4/6] Add bun notice and remove StackBlitz reference --- README.md | 6 +----- smart-contracts-hardhat/README.md | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 53d9f79..2df89ed 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Please check the versions used in the [`package.json`](./package.json) > A lot of these scripts should run with `ts-node` in development environnements, but you might be encountering issues because of ESM dependencies. -**The scripts will be run using [`bun`](https://bun.sh/docs/installation) and `bunx`. Make sure you have `bun` installed first.** +**This repository uses the [bun](https://bun.sh) toolkit to manage packages and run scripts.Make sure to [install it](https://bun.sh/docs/installation) first.** Then clone this repository and install its dependencies. @@ -51,7 +51,3 @@ We highly recommend that developers fetch and store profile or asset data using - IPFS Gateway: `https://api.universalprofile.cloud/ipfs` > LUKSO does not provide an official gateway for uploading asset data. - -### Run in browser - -Open this project on [StackBlitz](https://stackblitz.com/github/lukso-network/lukso-playground) and start coding right away. diff --git a/smart-contracts-hardhat/README.md b/smart-contracts-hardhat/README.md index 725ac3b..d1eca63 100644 --- a/smart-contracts-hardhat/README.md +++ b/smart-contracts-hardhat/README.md @@ -9,6 +9,8 @@ This project is used as a guide to show how to setup HardHat to interact with ** ## Setup +**This Hardhat repository uses the [bun](https://bun.sh) package manager. Make sure to [install it](https://bun.sh/docs/installation) first.** + Install the dependencies ```bash From 8835cd3de282b78894c86b747847c7eda6554215 Mon Sep 17 00:00:00 2001 From: Hugo Masclet Date: Thu, 22 Feb 2024 15:35:19 +0100 Subject: [PATCH 5/6] Fix TypeScript typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2df89ed..ae41f5b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ cd lukso-playground && bun install ### Run locally -Run the Typescript code of one file within the terminal using `bun`. +Run the TypeScript code of one file within the terminal using `bun`. ```bash bun file-path/script.ts From b622230817766ad6e02d5fa370ac59eed082f22f Mon Sep 17 00:00:00 2001 From: Hugo Masclet Date: Thu, 22 Feb 2024 16:25:48 +0100 Subject: [PATCH 6/6] Fix prettier and eslint --- .eslintrc.cjs | 18 ---------- .eslintrc.json | 19 ++++++++++ .github/workflows/build-lint.yaml | 1 - .prettierignore | 1 + .prettierrc | 25 +++---------- digital-assets/backend-token-transaction.ts | 6 +++- digital-assets/encode-metadata.ts | 14 ++++++-- digital-assets/extract-asset-data.ts | 33 +++++++++++++----- digital-assets/fetch-tokenid-metadata.ts | 23 +++++++++--- interface-detection/erc165-interface-check.ts | 22 ++++++++---- key-manager/set-permissions.ts | 14 +++++--- metadata-detection/digital-asset-check.ts | 11 ++++-- metadata-detection/profile-check.ts | 4 ++- metadata-detection/vault-check.ts | 8 +++-- package.json | 4 +-- smart-contracts-hardhat/.eslintrc.json | 13 +++++++ smart-contracts-hardhat/.prettierrc | 23 ++++++++++++ smart-contracts-hardhat/bun.lockb | Bin 355858 -> 379867 bytes smart-contracts-hardhat/package.json | 2 ++ transfer-lyx/backend-lyx-transaction.ts | 6 +++- universal-profile/extract-profile-data.ts | 13 +++++-- universal-profile/fetch-json-data.ts | 4 ++- .../get-controller-permissions.ts | 12 +++++-- universal-profile/register-asset-backend.ts | 11 ++++-- 24 files changed, 202 insertions(+), 85 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100644 .eslintrc.json create mode 100644 .prettierignore create mode 100644 smart-contracts-hardhat/.eslintrc.json create mode 100644 smart-contracts-hardhat/.prettierrc diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index c8843f2..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true, - node: true, - }, - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 12, - sourceType: 'module', - }, - plugins: ['@typescript-eslint', 'prettier'], - rules: { - 'prettier/prettier': 'error', - '@typescript-eslint/no-explicit-any': 'off', - }, -}; diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..df62db4 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "plugins": ["@typescript-eslint", "prettier"], + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module" + }, + "rules": { + "prettier/prettier": "error", + "@typescript-eslint/no-explicit-any": "off" + }, + "ignorePatterns": ["smart-contracts-hardhat/"] +} diff --git a/.github/workflows/build-lint.yaml b/.github/workflows/build-lint.yaml index 86a7987..c4e9d20 100644 --- a/.github/workflows/build-lint.yaml +++ b/.github/workflows/build-lint.yaml @@ -13,7 +13,6 @@ on: jobs: build: runs-on: ubuntu-latest - steps: - uses: actions/checkout@v4 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a9e5d44 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +smart-contract-hardhat \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index d00fc29..dc75c8a 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,23 +1,6 @@ { - "plugins": ["prettier-plugin-solidity"], - "overrides": [ - { - "files": ["*.js", "*.ts"], - "options": { - "tabWidth": 2, - "printWidth": 100, - "trailingComma": "all", - "singleQuote": true, - "semi": true - } - }, - { - "files": "*.sol", - "options": { - "tabWidth": 4, - "printWidth": 80, - "compiler": "0.8.15" - } - } - ] + "trailingComma": "all", + "tabWidth": 2, + "semi": true, + "singleQuote": true } diff --git a/digital-assets/backend-token-transaction.ts b/digital-assets/backend-token-transaction.ts index c119d46..d46d513 100644 --- a/digital-assets/backend-token-transaction.ts +++ b/digital-assets/backend-token-transaction.ts @@ -11,7 +11,11 @@ const controller = '0x...'; // Replace with the controller address // Instantiate the profile contract with an address const userProfileAddress = '0x...'; // Replace with the user's profile address -const myUniversalProfile = new ethers.Contract(userProfileAddress, UniversalProfile.abi, provider); +const myUniversalProfile = new ethers.Contract( + userProfileAddress, + UniversalProfile.abi, + provider, +); // Instantiate the token contract with an address const tokenAddress = '0x...'; // Replace with the token contract address diff --git a/digital-assets/encode-metadata.ts b/digital-assets/encode-metadata.ts index e14caef..764460e 100644 --- a/digital-assets/encode-metadata.ts +++ b/digital-assets/encode-metadata.ts @@ -1,6 +1,6 @@ import { ERC725 } from '@erc725/erc725.js'; +import { EncodeDataInput } from '@erc725/erc725.js/build/main/src/types/decodeData.js'; import LSP4DigitalAssetSchema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; -import { EncodeDataInput } from '@erc725/erc725.js/build/main/src/types/decodeData'; const LSP4SampleJSON = { LSP4Metadata: { @@ -71,11 +71,19 @@ const lsp4SampleMetadata: EncodeDataInput[] = [ // Encode the new LSP4 metadata as Verifiable URI // https://docs.lukso.tech/tools/erc725js/classes/ERC725#encodedata -const encodedLSP4Metadata = ERC725.encodeData(lsp4SampleMetadata, LSP4DigitalAssetSchema); +const encodedLSP4Metadata = ERC725.encodeData( + lsp4SampleMetadata, + LSP4DigitalAssetSchema, +); console.log(encodedLSP4Metadata); const decodedLSP4Metadata = ERC725.decodeData( - [{ keyName: encodedLSP4Metadata.keys[0], value: encodedLSP4Metadata.values[0] }], + [ + { + keyName: encodedLSP4Metadata.keys[0], + value: encodedLSP4Metadata.values[0], + }, + ], LSP4DigitalAssetSchema, ); diff --git a/digital-assets/extract-asset-data.ts b/digital-assets/extract-asset-data.ts index a25bb2a..834d56c 100644 --- a/digital-assets/extract-asset-data.ts +++ b/digital-assets/extract-asset-data.ts @@ -8,7 +8,8 @@ const IPFS_GATEWAY = 'https://api.universalprofile.cloud/ipfs'; // 💡 Note: You can debug any smart contract by using the ERC725 Tools // 👉 https://erc725-inspect.lukso.tech/inspector?address=0x61b083f1fb63ba2F064990f01B233B547ED4F5Cb&network=mainnet -const SAMPLE_ASSET_CONTRACT_ADDRESS = '0x61b083f1fb63ba2F064990f01B233B547ED4F5Cb'; +const SAMPLE_ASSET_CONTRACT_ADDRESS = + '0x61b083f1fb63ba2F064990f01B233B547ED4F5Cb'; // Parameters for the ERC725 instance const config = { ipfsGateway: IPFS_GATEWAY }; @@ -51,7 +52,10 @@ async function getAssetProperties(assetJSON: any) { try { // Check if images are available - if (assetJSON.value.LSP4Metadata.images && assetJSON.value.LSP4Metadata.images.length > 0) { + if ( + assetJSON.value.LSP4Metadata.images && + assetJSON.value.LSP4Metadata.images.length > 0 + ) { assetImageData = assetJSON.value.LSP4Metadata.images; for (const imageData of assetImageData[0]) { // Assuming the first set of images is what we want @@ -61,16 +65,24 @@ async function getAssetProperties(assetJSON: any) { url: imageData.url.replace('ipfs://', IPFS_GATEWAY), }); } - console.log('Asset Image Links: ' + JSON.stringify(assetImageLinks, undefined, 2) + '\n'); - - fullSizeAssetImage = assetImageLinks.length > 0 ? assetImageLinks[0].url : null; + console.log( + 'Asset Image Links: ' + + JSON.stringify(assetImageLinks, undefined, 2) + + '\n', + ); + + fullSizeAssetImage = + assetImageLinks.length > 0 ? assetImageLinks[0].url : null; console.log('Full Size Asset Image Link: ' + fullSizeAssetImage + '\n'); } else { console.log('Asset does not have image data \n'); } // Check if icons are available - if (assetJSON.value.LSP4Metadata.icon && assetJSON.value.LSP4Metadata.icon.length > 0) { + if ( + assetJSON.value.LSP4Metadata.icon && + assetJSON.value.LSP4Metadata.icon.length > 0 + ) { iconImageData = assetJSON.value.LSP4Metadata.icon; for (const iconData of iconImageData) { assetIconLinks.push({ @@ -78,9 +90,14 @@ async function getAssetProperties(assetJSON: any) { }); } - console.log('Asset Icon Links: ' + JSON.stringify(assetIconLinks, undefined, 2) + '\n'); + console.log( + 'Asset Icon Links: ' + + JSON.stringify(assetIconLinks, undefined, 2) + + '\n', + ); - fullSizeIconImage = assetIconLinks.length > 0 ? assetIconLinks[0].url : null; + fullSizeIconImage = + assetIconLinks.length > 0 ? assetIconLinks[0].url : null; console.log('Full Size Icon Image Link: ' + fullSizeIconImage + '\n'); } else { console.log('Asset does not have icon data'); diff --git a/digital-assets/fetch-tokenid-metadata.ts b/digital-assets/fetch-tokenid-metadata.ts index 26ce54b..050a6ea 100644 --- a/digital-assets/fetch-tokenid-metadata.ts +++ b/digital-assets/fetch-tokenid-metadata.ts @@ -2,7 +2,10 @@ import { ethers } from 'ethers'; import { ERC725 } from '@erc725/erc725.js'; import lsp4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; -import { INTERFACE_IDS, ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants'; +import { + INTERFACE_IDS, + ERC725YDataKeys, +} from '@lukso/lsp-smart-contracts/constants'; import lsp8Artifact from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'; async function fetchTokenIdMetadata() { @@ -16,13 +19,20 @@ async function fetchTokenIdMetadata() { const provider = new ethers.JsonRpcProvider(RPC_URL); // Create contract instance - const myAsset = new ethers.Contract(SAMPLE_LSP8_ASSET, lsp8Artifact.abi, provider); + const myAsset = new ethers.Contract( + SAMPLE_LSP8_ASSET, + lsp8Artifact.abi, + provider, + ); - const isLSP8 = await myAsset.supportsInterface(INTERFACE_IDS.LSP8IdentifiableDigitalAsset); + const isLSP8 = await myAsset.supportsInterface( + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + ); if (isLSP8) { // Token ID as Bytes32 value (1) - const tokenID = '0x0000000000000000000000000000000000000000000000000000000000000001'; + const tokenID = + '0x0000000000000000000000000000000000000000000000000000000000000001'; // Get the encoded asset metadata const tokenIdMetadata = await myAsset.getDataForTokenId( @@ -40,7 +50,10 @@ async function fetchTokenIdMetadata() { }, ]); - console.log('Contract Metadata: ', JSON.stringify(decodedMetadata, undefined, 2)); + console.log( + 'Contract Metadata: ', + JSON.stringify(decodedMetadata, undefined, 2), + ); // Prepare IPFS link to fetch const contentID = decodedMetadata[0].value.url.replace('ipfs://', ''); diff --git a/interface-detection/erc165-interface-check.ts b/interface-detection/erc165-interface-check.ts index 0fd981d..a467651 100644 --- a/interface-detection/erc165-interface-check.ts +++ b/interface-detection/erc165-interface-check.ts @@ -9,7 +9,8 @@ import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts'; // 💡 Note: You can debug any smart contract by using the ERC725 Tools // 👉 https://erc725-inspect.lukso.tech/inspector?address=0x61b083f1fb63ba2F064990f01B233B547ED4F5Cb&network=mainnet -const SAMPLE_ASSET_CONTRACT_ADDRESS = '0x61b083f1fb63ba2F064990f01B233B547ED4F5Cb'; +const SAMPLE_ASSET_CONTRACT_ADDRESS = + '0x61b083f1fb63ba2F064990f01B233B547ED4F5Cb'; // https://docs.lukso.tech/networks/mainnet/parameters const RPC_URL = 'https://rpc.lukso.gateway.fm'; @@ -20,20 +21,27 @@ const myAsset = new ERC725(lsp4Schema, SAMPLE_ASSET_CONTRACT_ADDRESS, RPC_URL, { const isLSP7 = await myAsset.supportsInterface(INTERFACE_IDS.LSP7DigitalAsset); -const isLSP8 = await myAsset.supportsInterface(INTERFACE_IDS.LSP8IdentifiableDigitalAsset); +const isLSP8 = await myAsset.supportsInterface( + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, +); if (isLSP7) { - console.log(`✅ The contract: ${SAMPLE_ASSET_CONTRACT_ADDRESS} supports the LSP7 interface ID`); + console.log( + `✅ The contract: ${SAMPLE_ASSET_CONTRACT_ADDRESS} supports the LSP7 interface ID`, + ); } if (isLSP8) { - console.log(`✅ The contract: ${SAMPLE_ASSET_CONTRACT_ADDRESS} supports the LSP8 interface ID`); + console.log( + `✅ The contract: ${SAMPLE_ASSET_CONTRACT_ADDRESS} supports the LSP8 interface ID`, + ); } const provider = new ethers.JsonRpcProvider(RPC_URL); // 💡 Note: You can debug any smart contract by using the ERC725 Tools // 👉 https://erc725-inspect.lukso.tech/inspector?address=0xe65e927d0eccaaab6972170b489d3c1455955116&network=mainnet -const universalProfileContractAddress = '0xe65e927d0eccaaab6972170b489d3c1455955116'; +const universalProfileContractAddress = + '0xe65e927d0eccaaab6972170b489d3c1455955116'; // Create an instance of the Universal Profile const myProfileContract = new ethers.Contract( @@ -42,7 +50,9 @@ const myProfileContract = new ethers.Contract( provider, ); -const isLSP0 = await myProfileContract.supportsInterface(INTERFACE_IDS.LSP0ERC725Account); +const isLSP0 = await myProfileContract.supportsInterface( + INTERFACE_IDS.LSP0ERC725Account, +); if (isLSP0) { console.log( diff --git a/key-manager/set-permissions.ts b/key-manager/set-permissions.ts index caaaa32..f055e8b 100644 --- a/key-manager/set-permissions.ts +++ b/key-manager/set-permissions.ts @@ -1,5 +1,8 @@ import { ethers } from 'ethers'; -import { PERMISSIONS, ERC725YDataKeys } from '@lukso/lsp-smart-contracts/constants'; +import { + PERMISSIONS, + ERC725YDataKeys, +} from '@lukso/lsp-smart-contracts/constants'; import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json'; // Connect to the LUKSO Testnet @@ -9,7 +12,8 @@ const provider = new ethers.JsonRpcProvider(RPC_ENDPOINT); const myUniversalProfileAddress = '0x9fc7e5095A054dfA3c6b237E0e5d686638394248'; const myKeyManagerAddress = '0x87fa9105cA247897Acb4F12Ddf6EC3CEF23F6059'; -const walletPrivateKey = '0x...'; // Replace with your wallet's private key +const walletPrivateKey = + '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; // Replace with your wallet's private key const wallet = new ethers.Wallet(walletPrivateKey, provider); const universalProfile = new ethers.Contract( @@ -26,9 +30,11 @@ const bobPermissions = PERMISSIONS.SETDATA; async function setPermission() { try { const permissionData = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + bobAddress.substring(2), // allow Bob to setData on your UP + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + + bobAddress.substring(2), // allow Bob to setData on your UP ERC725YDataKeys.LSP6['AddressPermissions[]'].length, // length of AddressPermissions[] - ERC725YDataKeys.LSP6['AddressPermissions[]'].index + '00000000000000000000000000000001', // add Bob's address into the list of permissions + ERC725YDataKeys.LSP6['AddressPermissions[]'].index + + '00000000000000000000000000000001', // add Bob's address into the list of permissions ]; const permissionParams = [ diff --git a/metadata-detection/digital-asset-check.ts b/metadata-detection/digital-asset-check.ts index 4976866..aa4c357 100644 --- a/metadata-detection/digital-asset-check.ts +++ b/metadata-detection/digital-asset-check.ts @@ -6,7 +6,12 @@ import lsp4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json'; const assetContractAddress = '0x86e817172b5c07f7036bf8aa46e2db9063743a83'; // Initatiate erc725.js -const erc725js = new ERC725(lsp4Schema, assetContractAddress, 'https://rpc.lukso.gateway.fm', {}); +const erc725js = new ERC725( + lsp4Schema, + assetContractAddress, + 'https://rpc.lukso.gateway.fm', + {}, +); // Verify if the standard is supported (value !== null) // 📚 https://docs.lukso.tech/standards/tokens/LSP4-Digital-Asset-Metadata#supportedstandardslsp4digitalasset @@ -14,7 +19,9 @@ const data = await erc725js.getData('SupportedStandards:LSP4DigitalAsset'); const isLSP4 = data.value !== null; if (isLSP4) { - console.log(`✅ The contract: ${assetContractAddress} supports the LSP4DigitalAsset standard`); + console.log( + `✅ The contract: ${assetContractAddress} supports the LSP4DigitalAsset standard`, + ); } else { console.log( `❌ The address: ${assetContractAddress} does not supports the LSP4DigitalAsset standard`, diff --git a/metadata-detection/profile-check.ts b/metadata-detection/profile-check.ts index 9388b73..11c8bdb 100644 --- a/metadata-detection/profile-check.ts +++ b/metadata-detection/profile-check.ts @@ -20,7 +20,9 @@ const data = await erc725js.getData('SupportedStandards:LSP3Profile'); const isLSP3 = data.value !== null; if (isLSP3) { - console.log(`✅ The contract: ${profileContractAddress} supports the LSP3Profile standard`); + console.log( + `✅ The contract: ${profileContractAddress} supports the LSP3Profile standard`, + ); } else { console.log( `❌ The address: ${profileContractAddress} does not supports the LSP3Profile standard`, diff --git a/metadata-detection/vault-check.ts b/metadata-detection/vault-check.ts index b1c88b4..893ce87 100644 --- a/metadata-detection/vault-check.ts +++ b/metadata-detection/vault-check.ts @@ -19,7 +19,11 @@ const data = await erc725js.getData('SupportedStandards:LSP9Vault'); const isLSP9 = data.value !== null; if (isLSP9) { - console.log(`✅ The contract: ${vaultContractAddress} supports the LSP9Vault standard`); + console.log( + `✅ The contract: ${vaultContractAddress} supports the LSP9Vault standard`, + ); } else { - console.log(`❌ The address: ${vaultContractAddress} does not supports the LSP9Vault standard`); + console.log( + `❌ The address: ${vaultContractAddress} does not supports the LSP9Vault standard`, + ); } diff --git a/package.json b/package.json index a92a049..77e072f 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ }, "homepage": "https://github.com/lukso-network/lukso-playground#readme", "scripts": { - "lint": "eslint . --ext .ts,.js", - "lint:fix": "eslint . --ext .ts,.js --fix" + "lint": "eslint .", + "lint:fix": "eslint . --fix" }, "devDependencies": { "@erc725/erc725.js": "^0.23.0", diff --git a/smart-contracts-hardhat/.eslintrc.json b/smart-contracts-hardhat/.eslintrc.json new file mode 100644 index 0000000..53818c2 --- /dev/null +++ b/smart-contracts-hardhat/.eslintrc.json @@ -0,0 +1,13 @@ +{ + "ignorePatterns": ["artifacts/", "cache/", "dist/", "types/", "contracts.ts"], + "plugins": ["@typescript-eslint/eslint-plugin", "prettier"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "rules": { + "prettier/prettier": "error", + "@typescript-eslint/no-explicit-any": "off" + }, + "root": true +} diff --git a/smart-contracts-hardhat/.prettierrc b/smart-contracts-hardhat/.prettierrc new file mode 100644 index 0000000..d00fc29 --- /dev/null +++ b/smart-contracts-hardhat/.prettierrc @@ -0,0 +1,23 @@ +{ + "plugins": ["prettier-plugin-solidity"], + "overrides": [ + { + "files": ["*.js", "*.ts"], + "options": { + "tabWidth": 2, + "printWidth": 100, + "trailingComma": "all", + "singleQuote": true, + "semi": true + } + }, + { + "files": "*.sol", + "options": { + "tabWidth": 4, + "printWidth": 80, + "compiler": "0.8.15" + } + } + ] +} diff --git a/smart-contracts-hardhat/bun.lockb b/smart-contracts-hardhat/bun.lockb index 77769ac909177219ceef58b87b28be91849e7292..da7d3d0e935aae72125778407c6d5a772110ff1a 100755 GIT binary patch delta 70696 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 delta 56416 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 U9ah`cr~Fj)z=D_)>WPj24+n;PGXMYp diff --git a/smart-contracts-hardhat/package.json b/smart-contracts-hardhat/package.json index f192d32..b9ec641 100644 --- a/smart-contracts-hardhat/package.json +++ b/smart-contracts-hardhat/package.json @@ -5,7 +5,9 @@ }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", "dotenv": "^16.3.1", + "eslint": "^8.56.0", "ethers": "^6.10.0", "hardhat": "^2.19.5", "prettier": "^3.2.5", diff --git a/transfer-lyx/backend-lyx-transaction.ts b/transfer-lyx/backend-lyx-transaction.ts index 979d5cc..edc376e 100644 --- a/transfer-lyx/backend-lyx-transaction.ts +++ b/transfer-lyx/backend-lyx-transaction.ts @@ -13,7 +13,11 @@ const controller = '0x...'; // Replace with the controller address // Instantiate Universal Profile const userProfileAddress = '0x...'; // Replace with the user's profile address -const myUniversalProfile = new ethers.Contract(userProfileAddress, UniversalProfile.abi, provider); +const myUniversalProfile = new ethers.Contract( + userProfileAddress, + UniversalProfile.abi, + provider, +); (async () => { try { diff --git a/universal-profile/extract-profile-data.ts b/universal-profile/extract-profile-data.ts index 7797f25..1e89581 100644 --- a/universal-profile/extract-profile-data.ts +++ b/universal-profile/extract-profile-data.ts @@ -109,7 +109,10 @@ async function fetchPictureData(address: string) { } for (const i in profileImagesIPFS) { - profileImageLinks.push([i, profileImagesIPFS[i].url.replace('ipfs://', IPFS_GATEWAY)]); + profileImageLinks.push([ + i, + profileImagesIPFS[i].url.replace('ipfs://', IPFS_GATEWAY), + ]); } fullSizeBackgroundImg = backgroundImageLinks[0][1]; @@ -119,10 +122,14 @@ async function fetchPictureData(address: string) { console.log('Fullsize Background Image: ' + fullSizeBackgroundImg + '\n'); console.log('Fullsize Background Image: ' + fullSizeProfileImg + '\n'); console.log( - 'Background Image Links: ' + JSON.stringify(backgroundImageLinks, undefined, 2) + '\n', + 'Background Image Links: ' + + JSON.stringify(backgroundImageLinks, undefined, 2) + + '\n', ); console.log( - 'Background Image Links: ' + JSON.stringify(profileImageLinks, undefined, 2) + '\n', + 'Background Image Links: ' + + JSON.stringify(profileImageLinks, undefined, 2) + + '\n', ); } catch (error) { return console.log('Could not fetch images: ', error); diff --git a/universal-profile/fetch-json-data.ts b/universal-profile/fetch-json-data.ts index 4942a17..46731e7 100644 --- a/universal-profile/fetch-json-data.ts +++ b/universal-profile/fetch-json-data.ts @@ -27,5 +27,7 @@ const receivedAssetsDataKey = await erc725js.fetchData('LSP5ReceivedAssets[]'); console.log(receivedAssetsDataKey); // Fetch the profile's universal receiver -const universalReceiverDataKey = await erc725js.fetchData('LSP1UniversalReceiverDelegate'); +const universalReceiverDataKey = await erc725js.fetchData( + 'LSP1UniversalReceiverDelegate', +); console.log(universalReceiverDataKey); diff --git a/universal-profile/get-controller-permissions.ts b/universal-profile/get-controller-permissions.ts index cdd1968..a6934bf 100644 --- a/universal-profile/get-controller-permissions.ts +++ b/universal-profile/get-controller-permissions.ts @@ -19,7 +19,10 @@ async function getPermissionedAddresses() { const result = await erc725.getData('AddressPermissions[]'); if (!result) { - console.error('No controllers listed under UP at address ', myUniversalProfileAddress); + console.error( + 'No controllers listed under UP at address ', + myUniversalProfileAddress, + ); } if (Array.isArray(result.value)) { @@ -33,11 +36,14 @@ async function getPermissionedAddresses() { }); // Decode the permission of each address - const decodedPermission = erc725.decodePermissions(addressPermission.value as string); + const decodedPermission = erc725.decodePermissions( + addressPermission.value as string, + ); // Display the permission in a readable format console.log( - `decoded permission for ${address} = ` + JSON.stringify(decodedPermission, null, 2), + `decoded permission for ${address} = ` + + JSON.stringify(decodedPermission, null, 2), ); } } diff --git a/universal-profile/register-asset-backend.ts b/universal-profile/register-asset-backend.ts index 09cf244..f26b43d 100644 --- a/universal-profile/register-asset-backend.ts +++ b/universal-profile/register-asset-backend.ts @@ -36,9 +36,14 @@ const provider = new ethers.JsonRpcProvider(RPC_ENDPOINT); const myWallet = new ethers.Wallet(PRIVATE_KEY, provider); // 1. encode the data keys related to LSP12IssuedAssets[] -const erc725 = new ERC725(LSP12Schema, UNIVERSAL_PROFILE_ADDRESS, RPC_ENDPOINT, { - ipfsGateway: 'https://api.universalprofile.cloud/ipfs', -}); +const erc725 = new ERC725( + LSP12Schema, + UNIVERSAL_PROFILE_ADDRESS, + RPC_ENDPOINT, + { + ipfsGateway: 'https://api.universalprofile.cloud/ipfs', + }, +); const allAssetAddresses = issuedAssets.map((asset) => asset.address);