π Read Digital Asset Data
The full code of this example can be found in the πΎ lukso-playground repository.
On LUKSO, Digital Assets are created using the LSP7 - Digital Asset and LSP8 - Identifiable Digital Asset standards. The data of each digital asset lives in its own ERC725Y storage. This tutorial teaches you how to fetch and read this data.
Before following this guide, it is recommended to be a bit familiar with the token standards:
You can use the π ERC725 Inspect tool for inspecting assets within the browser.
Setupβ
You will need the following to follow this tutorial:
- Address of a digital asset (Example asset address on testnet:
0x0514A829C832639Afcc02D257154A9DaAD8fa21B
). @lukso/lsp-smart-contracts
packageerc725.js
npm i @lukso/lsp-smart-contracts @erc725/erc725.js
Check if the contract is a Digital Assetβ
If you are using the π lsp-smart-contracts library, you can fetch the list of interfaceId
directly from the package's constants called INTERFACE_IDS
.
Optionally, you can also find a full list of interface IDs on the Contracts > Interface ID page and input them manually.
First, we need to check if the contract is a digital asset, as either an LSP7 or an LSP8 smart contract. To do so, we will do the same way as shown in the Interface Detection guide: call the supportsInterface(bytes4)
function in te smart contract, checking for various interface IDs.
- ethers
- web3
import { ethers } from 'ethers';
import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts';
const provider = new ethers.JsonRpcProvider(
'https://rpc.testnet.lukso.network',
);
const myAsset = new ethers.Contract('<myAssetAddress>', [
{
inputs: [
{
internalType: 'bytes4',
name: '_interfaceId',
type: 'bytes4',
},
],
name: 'supportsInterface',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
provider,
]);
const isLSP7 = await myAsset.supportsInterface(INTERFACE_IDS.LSP7DigitalAsset);
const isLSP8 = await myAsset.supportsInterface(
INTERFACE_IDS.LSP8IdentifiableDigitalAsset,
);
console.log(isLSP7, isLSP8); // each, true or false
import Web3 from 'web3';
import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts';
const web3 = new Web3('https://rpc.testnet.lukso.network');
const myAsset = new web3.eth.Contract(
[
{
inputs: [
{
internalType: 'bytes4',
name: '_interfaceId',
type: 'bytes4',
},
],
name: 'supportsInterface',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
],
'<myAssetAddress>',
);
const isLSP7 = await myAsset.methods
.supportsInterface(INTERFACE_IDS.LSP7DigitalAsset)
.call();
const isLSP8 = await myAsset.methods
.supportsInterface(INTERFACE_IDS.LSP8IdentifiableDigitalAsset)
.call();
console.log(isLSP7, isLSP8); // each, true or false
Fetch the Asset Metadataβ
LSP4 - Digital Asset Metadata describes the data within LSP7 and LSP8 asset's ERC725Y data storage.
The following data keys can be fetched π
ποΈ Data Key | Value contained inside this data key |
---|---|
SupportedStandards:LSP4DigitalAsset | A hex literal value confirming the ERC725Y contract contains metadata keys for the LSP4DigitalAsset standard. |
LSP4Metadata | The JSON file with asset descriptions and images. |
LSP4Creators[] | An array of all creators of the asset. |
LSP4CreatorsMap:<address> | A mapping of creator-specific information. |
LSP4TokenType | The asset's token type (encoded as a uint256 number). |
LSP4TokenSymbol | The utf8 hex characters of the string representing the asset's symbol. |
LSP4TokenName | The utf8 hex characters of the string representing the asset's name. |
To retrieve and decode the value stored under this data keys, we will use erc725.js and instantiate the class with:
- the LSP4 Schema that defines the data keys above and how to decode them
- the address of your digital asset
- an RPC URL
- an IPFS gateway to fetch any off-chain data linked to the contract storage
import { ERC725 } from '@erc725/erc725.js';
import lsp4Schema from '@erc725/erc725.js/schemas/LSP4DigitalAsset.json';
import { INTERFACE_IDS } from '@lukso/lsp-smart-contracts';
const erc725js = new ERC725(
lsp4Schema,
'0x0514A829C832639Afcc02D257154A9DaAD8fa21B', // address of the digital asset contract
'https://4201.rpc.thirdweb.com',
{
ipfsGateway: 'https://api.universalprofile.cloud/ipfs',
},
);
We can fetch the digital asset data in three ways:
- using
getData()
without parameters. This will fetch the value of all data keys at once. - using
getData("DataKeyName")
to fetch the value of a specific data key. For instancegetData("LSP4Metadata")
. - using
fetchData('LSP4Metadata')
which decodes theVerifiableURI
to extract the JSON metadata file link and fetch its content from IPFS (or another storage service).
Asset Name and Symbolβ
// Fetch the asset's name
const tokenName = await erc725js.fetchData('LSP4TokenName');
console.log(tokenName);
/**
{
key: '0xdeba1e292f8ba88238e10ab3c7f88bd4be4fac56cad5194b6ecceaf653468af1',
name: 'LSP4TokenName',
value: 'upturn: MINT PASS [UPT0001]',
}
*/
// Fetch the asset's symbol
const tokenSymbol = await erc725js.fetchData('LSP4TokenSymbol');
console.log(tokenSymbol);
/**
{
key: '0x2f0a68ab07768e01943a599e73362a0e17a63a72e94dd2e384d2c1d4db932756',
name: 'LSP4TokenSymbol',
value: 'UPT',
}
*/
Global Token Informationβ
To fetch the whole JSON file of the asset's metadata, you can use the following 2 functions of the erc725js
library:
fetchData('LSP4Metadata')
: This will download and decode the content ofVerifiableURI
as JSON.getData(LSP4Metadata)
: This will retrieve the raw data value from the smart contract. You will then need to decode theVerifiableURI
maunually usingdecodeData(...)
.
// Download and verify the asset metadata JSON file
const assetMetadata = await erc725js.fetchData('LSP4Metadata');
console.log(assetMetadata);
Show result
{
"key": "0x9afb95cacc9f95858ec44aa8c3b685511002e30ae54415823f406128b85b238e",
"name": "LSP4Metadata",
"value": {
"LSP4Metadata": {
"description": "A MINT PASS enables 1x Token Deployment using the upturn protocol",
"links": [
{
"title": "upturnOS",
"url": "https://upturn.live"
}
],
"icon": [
{
"width": 1600,
"height": 1584,
"url": "ipfs://bafybeieyp4gvgprefvd6exm4sdbehkzlu2rmh57ferp3tmfb2oihfg6tp4",
"verification": {
"method": "keccak256(bytes)",
"data": "0x996302e00ef0226f12d44c029fb2c82290f31e2209013cd5c0502840f8e57d0e"
}
}
],
"backgroundImage": [
{
"width": 1920,
"height": 1080,
"url": "ipfs://bafybeiediqal3fvzlmu5c4kc2kei2irq5rggi5hkmqecvefcdiaeg2bgbu",
"verification": {
"method": "keccak256(bytes)",
"data": "0xf80f3cfd9f905186fb30bcbd77c4111e4afe5fba75c678928e7fc2452f74cbc1"
}
}
],
"assets": [
{
"url": "ipfs://bafkreibxq4lrx5s4q5lag5wsw7pivugcfkb4ync4y23wjgy4brbusi7tsy",
"fileType": "image/png",
"verification": {
"method": "keccak256(bytes)",
"data": "0x4ec65a52385593b134770e5612cfcb54c0a77aba2121964e0b27ba037cf4eea6"
}
}
],
"images": [
[
{
"width": 1440,
"height": 1440,
"url": "ipfs://bafkreibxq4lrx5s4q5lag5wsw7pivugcfkb4ync4y23wjgy4brbusi7tsy",
"verification": {
"method": "keccak256(bytes)",
"data": "0x4ec65a52385593b134770e5612cfcb54c0a77aba2121964e0b27ba037cf4eea6"
}
}
]
]
}
}
}
List of Creatorsβ
// Fetch all creators of the asset
const assetCreatorsList = await erc725js.fetchData('LSP4Creators[]');
console.log(assetCreatorsList);
/**
// Creator List (empty, no creators set)
{
key: '0x114bd03b3a46d48759680d81ebb2b414fda7d030a7105a851867accf1c2352e7',
name: 'LSP4Creators[]',
value: []
}
*/
Get Creator basic infosβ
If one of the creator contains the LSP0ERC725Account
interface ID (0x...
), it is likely to be a Universal Profile! π
Follow the guide Read Profile Data to retrieve the profile infos!
The LSP4CreatorsMap:<address>
is a Mapping data key that requires a dynamic input. To fetch its info, use the function below, providing the creator address as input to the dynamicKeyParts
property of the object parameter.
// Fetch creator-specific information
const creatorInformation = await erc725js.fetchData([
{
keyName: 'LSP4CreatorsMap:<address>',
// Sample creator address
dynamicKeyParts: '0x9139def55c73c12bcda9c44f12326686e3948634',
},
]);
console.log(creatorInformation);
// Dynamic Creator Map Retrieval
/*
* Creator Map for 0x9..8634 (empty, no data set)
* Key Format: '0x6de85eaf5d982b4e5da00000<myCreatorAddress>'
* Name Format: 'LSP4CreatorsMap:<myCreatorAddress>'
[
{
key: '0x6de85eaf5d982b4e5da000009139def55c73c12bcda9c44f12326686e3948634',
name: 'LSP4CreatorsMap:9139def55c73c12bcda9c44f12326686e3948634',
value: [],
},
];
*/
Interpret Data based on Token Typeβ
If both, contract and metadata standard are aligned, Finally we need to determine the LSP4 Token Type in order to interpret the metadata correctly.
At this point, you should be able to identify if the digital asset is a:
- LSP7 - Token
- LSP7 - NFT
- LSP8 - NFT
- LSP8 - Collection
Based on the token type, the information of the LSP4 Digital Metadata can be interpreted differently:
- As global token information of the contract (Token or LSP7 NFT)
- To each individual token ID (LSP8 NFT or Collection)
- If your asset is a Token (
tokenType = 0
), individual metadata cant be set, due to the lack of token IDs. - If your asset is an NFT (
tokenType = 1
), individual metadata may be set in addition to the global token information. - If your asset is a Collection (
tokenType = 2
), the token ID-specific medatada is mandatory.