Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

fix: Update for fetching LSP8 metadata based on token id type #122

Merged
merged 16 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions models/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class AssetModel extends BaseModel {
description: this.string(''),
links: this.attr([]),
tokenId: this.string(''),
tokenIdType: this.string(''),
tokenIdType: this.number(null),
isNativeToken: this.boolean(false),
hash: this.string(''),
verification: this.attr({}),
Expand All @@ -46,7 +46,7 @@ export class AssetModel extends BaseModel {
declare description?: string
declare links?: LinkMetadata[]
declare tokenId?: string
declare tokenIdType?: string
declare tokenIdType?: number
declare isNativeToken?: boolean
declare hash: string
declare verification?: ImageMetadata['verification']
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"typechain": "typechain --target web3-v1 --out-dir types/contracts/ './node_modules/@lukso/lsp-smart-contracts/artifacts/*.json'"
},
"devDependencies": {
"@erc725/erc725.js": "0.21.2",
"@erc725/erc725.js": "0.21.1",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@formatjs/intl": "^2.9.6",
"@lukso/lsp-smart-contracts": "0.12.1",
Expand Down
2 changes: 1 addition & 1 deletion repositories/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class AssetRepository extends Repository<AssetModel> {
}

if (storageAsset.standard === 'LSP8IdentifiableDigitalAsset') {
assetData = await fetchLsp8Data(
assetData = await getLsp8Data(
assetAddress,
storageAsset?.tokenIdType,
storageAsset?.tokenId
Expand Down
51 changes: 0 additions & 51 deletions shared/schemas/LSP8IdentifiableDigitalAsset.json

This file was deleted.

18 changes: 12 additions & 6 deletions types/assets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { INTERFACE_IDS, ImageMetadata } from '@lukso/lsp-smart-contracts'
import {
INTERFACE_IDS,
ImageMetadata,
LSP8_TOKEN_ID_TYPES,
} from '@lukso/lsp-smart-contracts'

export type InterfaceId = keyof typeof INTERFACE_IDS

Expand All @@ -16,11 +20,13 @@ export enum AssetFilter {
created = 'created',
}

export enum Lsp8TokenIdType {
address = '1',
number = '2',
bytes32 = '3',
}
export const Lsp8TokenIdType = {
NUMBER: 0,
STRING: 1,
UNIQUE_ID: 2,
HASH: 3,
ADDRESS: 4,
} as typeof LSP8_TOKEN_ID_TYPES

export type Base64EncodedImage = `data:image/jpeg;base64${string}`

Expand Down
5 changes: 2 additions & 3 deletions utils/fetchAsset.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Asset } from '@/models/asset'

export const fetchAsset = async (
address: Address,
profileAddress?: Address,
tokenIds?: string[]
): Promise<Asset[]> => {
) => {
const standard = await detectStandard(address)

switch (standard) {
Expand All @@ -16,6 +14,7 @@ export const fetchAsset = async (
}

default:
console.warn(`Asset ${address} standard is not supported`)
return []
}
}
3 changes: 2 additions & 1 deletion utils/fetchLSP7Assets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'
import { AbiItem } from 'web3-utils'

import { ImageMetadataEncoded } from '@/types/assets'
import { LSP7DigitalAsset as LSP7DigitalAssetInterface } from '@/types/contracts'
Expand All @@ -13,7 +14,7 @@ export const fetchLsp7Assets = async (

const { contract } = useWeb3(PROVIDERS.RPC)
const lsp7Contract = contract<LSP7DigitalAssetInterface>(
LSP7DigitalAsset.abi as any,
LSP7DigitalAsset.abi as AbiItem[],
address
)
let balance = ''
Expand Down
5 changes: 3 additions & 2 deletions utils/fetchLSP8Assets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import LSP8IdentifiableDigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP8IdentifiableDigitalAsset.json'
import { AbiItem } from 'web3-utils'

import { LSP8IdentifiableDigitalAsset as LSP8IdentifiableDigitalAssetInterface } from '@/types/contracts/LSP8IdentifiableDigitalAsset'
import { Asset } from '@/models/asset'
Expand All @@ -11,7 +12,7 @@ export const fetchLsp8Assets = async (
): Promise<Asset[]> => {
const { contract } = useWeb3(PROVIDERS.RPC)
const lsp8Contract = contract<LSP8IdentifiableDigitalAssetInterface>(
LSP8IdentifiableDigitalAsset.abi as any,
LSP8IdentifiableDigitalAsset.abi as AbiItem[],
address
)
const tokenSupply = await lsp8Contract.methods.totalSupply().call()
Expand All @@ -36,7 +37,7 @@ export const fetchLsp8Assets = async (
tokenId,
address
)
const getData = await fetchLsp8Data(address, tokenIdType, tokenId)
const getData = await getLsp8Data(address, tokenIdType, tokenId)
const {
description,
images: metadataImages,
Expand Down
3 changes: 2 additions & 1 deletion utils/fetchLsp7Balance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import LSP7DigitalAsset from '@lukso/lsp-smart-contracts/artifacts/LSP7DigitalAsset.json'
import { AbiItem } from 'web3-utils'

import { LSP7DigitalAsset as LSP7DigitalAssetInterface } from '@/types/contracts'

Expand All @@ -8,7 +9,7 @@ export const fetchLsp7Balance = async (
) => {
const { contract } = useWeb3(PROVIDERS.RPC)
const lsp7Contract = contract<LSP7DigitalAssetInterface>(
LSP7DigitalAsset.abi as any,
LSP7DigitalAsset.abi as AbiItem[],
assetAddress
)

Expand Down
95 changes: 52 additions & 43 deletions utils/fetchLsp8Metadata.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,46 @@
import { LSP4DigitalAssetMetadataJSON } from '@lukso/lsp-smart-contracts'
import { ERC725JSONSchema } from '@erc725/erc725.js'
import ERC725, { ERC725JSONSchema } from '@erc725/erc725.js'
import LSP8IdentifiableDigitalAsset from '@erc725/erc725.js/schemas/LSP8IdentifiableDigitalAsset.json'

import { Lsp8TokenIdType } from '@/types/assets'
import LSP8IdentifiableDigitalAsset from '@/shared/schemas/LSP8IdentifiableDigitalAsset.json'

export const fetchLsp8Metadata = async (
tokenId: string,
assetAddress: Address
): Promise<[LSP4DigitalAssetMetadataJSON, string]> => {
const lsp8MetadataGetter = async (
tokenIdType: string,
tokenId: string
): Promise<LSP4DigitalAssetMetadataJSON> => {
const lsp8Metadata = await erc725.fetchData({
keyName: `LSP8MetadataJSON:<${tokenIdType}>`,
dynamicKeyParts: tokenId,
})
return validateLsp4MetaData(lsp8Metadata.value)
}

): Promise<[LSP4DigitalAssetMetadataJSON, number]> => {
const { getInstance } = useErc725()
const erc725 = getInstance(
assetAddress,
LSP8IdentifiableDigitalAsset as ERC725JSONSchema[]
)

try {
const lsp8DigitalAsset = await erc725.fetchData(['LSP8TokenIdType'])
const tokenIdType = lsp8DigitalAsset[0].value?.toString()
const lsp8DigitalAsset = await erc725.fetchData('LSP8TokenIdType')
const tokenIdType = Number(lsp8DigitalAsset.value)

// fetch LSP8MetadataJSON depending on tokenIdType
// fetch metadata depending on tokenIdType
switch (tokenIdType) {
case Lsp8TokenIdType.address:
case Lsp8TokenIdType.NUMBER:
return [
await lsp8MetadataGetter(
'address',
// ethers.utils.hexDataSlice(tokenId.toString(), 12)
tokenId.toString()
),
await getMetadata(tokenIdType, parseInt(tokenId).toString(), erc725),
tokenIdType,
]
case Lsp8TokenIdType.number:
case Lsp8TokenIdType.STRING:
case Lsp8TokenIdType.UNIQUE_ID:
case Lsp8TokenIdType.HASH:
return [
await lsp8MetadataGetter('uint256', parseInt(tokenId).toString()),
await getMetadata(tokenIdType, tokenId.toString(), erc725),
tokenIdType,
]
case Lsp8TokenIdType.bytes32:
case Lsp8TokenIdType.ADDRESS:
return [
await lsp8MetadataGetter('bytes32', tokenId.toString()),
await getMetadata(tokenIdType, tokenId.slice(0, 42), erc725),
tokenIdType,
]
default:
return [
{
LSP4Metadata: {
description: '',
links: [],
images: [[]],
icon: [],
assets: [],
},
},
'',
]
throw new Error(
`Unsupported LSP8 tokenIdType '${tokenIdType}' for '${assetAddress}' asset`
)
}
} catch (error) {
console.error(error)
Expand All @@ -76,14 +54,31 @@ export const fetchLsp8Metadata = async (
assets: [],
},
},
'',
-1,
]
}
}

export const fetchLsp8Data = async (
const tokenIdTypeString = (tokenIdType: number) => {
switch (tokenIdType) {
case Lsp8TokenIdType.NUMBER:
return 'uint256'
case Lsp8TokenIdType.STRING:
return 'string'
case Lsp8TokenIdType.UNIQUE_ID:
return 'bytes32'
case Lsp8TokenIdType.HASH:
return 'bytes32'
case Lsp8TokenIdType.ADDRESS:
return 'address'
default:
throw new Error(`Unsupported LSP8 tokenIdType '${tokenIdType}'`)
}
}

export const getLsp8Data = async (
assetAddress: string,
tokenIdType?: string,
tokenIdType?: number,
tokenId?: string
) => {
if (!tokenIdType || !tokenId) {
Expand All @@ -96,9 +91,23 @@ export const fetchLsp8Data = async (
LSP8IdentifiableDigitalAsset as ERC725JSONSchema[]
)
const metaData = await erc725.getData({
keyName: `LSP8MetadataJSON:<${tokenIdType}>`,
keyName: `LSP8MetadataTokenURI:<${tokenIdTypeString(tokenIdType)}>`,
dynamicKeyParts: tokenId,
})

return metaData
}

const getMetadata = async (
tokenIdType: number,
tokenIdValue: string,
erc725: ERC725
) => {
const lsp8Metadata = await erc725.fetchData([
{
keyName: `LSP8MetadataTokenURI:<${tokenIdTypeString(tokenIdType)}>`,
dynamicKeyParts: tokenIdValue,
},
])
return validateLsp4MetaData(lsp8Metadata[0].value)
}
4 changes: 3 additions & 1 deletion utils/supportInterface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { AbiItem } from 'web3-utils'

import { LSP0ERC725Account } from '@/types/contracts'

/**
Expand All @@ -16,7 +18,7 @@ export const supportInterface = async (

try {
const eip165Contract = contract<LSP0ERC725Account>(
eip165ABI as any,
eip165ABI as AbiItem[],
address
)
return await eip165Contract.methods.supportsInterface(interfaceId).call()
Expand Down
8 changes: 5 additions & 3 deletions utils/validateLSP4Metadata.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Verification } from '@erc725/erc725.js/build/main/src/types'
import { LSP4DigitalAssetMetadataJSON } from '@lukso/lsp-smart-contracts'
import {
LSP4DigitalAssetMetadataJSON,
AssetMetadata,
} from '@lukso/lsp-smart-contracts'

export const validateLsp4MetaData = (
LSP4MetadataJSON: any
Expand Down Expand Up @@ -142,6 +144,6 @@ export const validateVerification = (getDataObject: any) => {
'verification' in getDataObject?.value &&
'data' in getDataObject?.value?.verification &&
'method' in getDataObject?.value?.verification
? (getDataObject.value?.verification as Verification)
? (getDataObject.value?.verification as AssetMetadata['verification'])
: undefined
}
Loading