diff --git a/subgraph/package.json b/subgraph/package.json index 6e82ebd0..103d745a 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -8,7 +8,7 @@ "build:sepolia": "graph codegen && graph build --network sepolia", "build:mainnet": "graph codegen && graph build --network mainnet", "deploy:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 moleculeprotocol/ipnft-subgraph", - "deploy:sepolia": "env-cmd -x -f ../.env graph deploy ip-nft-sepolia --version-label 1.1.1 --node https://subgraphs.alchemy.com/api/subgraphs/deploy --ipfs https://ipfs.satsuma.xyz --deploy-key \\$SATSUMA_DEPLOY_KEY", + "deploy:sepolia": "env-cmd -x -f ../.env graph deploy ip-nft-sepolia --version-label 1.2.2 --node https://subgraphs.alchemy.com/api/subgraphs/deploy --ipfs https://ipfs.satsuma.xyz --deploy-key \\$SATSUMA_DEPLOY_KEY", "deploy:mainnet": "env-cmd -x -f ../.env graph deploy ip-nft-mainnet --version-label 1.1.0 --node https://subgraphs.alchemy.com/api/subgraphs/deploy --ipfs https://ipfs.satsuma.xyz --deploy-key \\$SATSUMA_DEPLOY_KEY", "create:local": "graph create --node http://localhost:8020/ moleculeprotocol/ipnft-subgraph", "remove:local": "graph remove --node http://localhost:8020/ moleculeprotocol/ipnft-subgraph", diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 9501460b..07965d53 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -7,6 +7,16 @@ type Ipnft @entity { listings: [Listing!] @derivedFrom(field: "ipnft") readers: [CanRead!] @derivedFrom(field: "ipnft") ipts: [IPT!] @derivedFrom(field: "ipnft") + metadata: IpnftMetadata + updatedAtTimestamp: BigInt +} + +type IpnftMetadata @entity { + id: ID! + name: String! + image: String! + description: String! + externalURL: String! } type IPT @entity { diff --git a/subgraph/src/ipnftMapping.ts b/subgraph/src/ipnftMapping.ts index b61de5ce..0579f535 100644 --- a/subgraph/src/ipnftMapping.ts +++ b/subgraph/src/ipnftMapping.ts @@ -7,14 +7,15 @@ import { store } from '@graphprotocol/graph-ts' import { + IPNFT as IPNFTContract, IPNFTMinted as IPNFTMintedEvent, - Reserved as ReservedEvent, - ReadAccessGranted as ReadAccessGrantedEvent, - Transfer as TransferEvent, MetadataUpdate as MetadataUpdateEvent, - IPNFT as IPNFTContract + ReadAccessGranted as ReadAccessGrantedEvent, + Reserved as ReservedEvent, + Transfer as TransferEvent } from '../generated/IPNFT/IPNFT' -import { Ipnft, Reservation, CanRead } from '../generated/schema' +import { IpnftMetadata as IpnftMetadataTemplate } from '../generated/templates' +import { CanRead, Ipnft, Reservation } from '../generated/schema' export function handleTransfer(event: TransferEvent): void { if (event.params.to == Address.zero()) { @@ -80,8 +81,14 @@ export function handleMint(event: IPNFTMintedEvent): void { ipnft.tokenURI = event.params.tokenURI ipnft.createdAt = event.block.timestamp ipnft.symbol = event.params.symbol + let ipfsLocation = event.params.tokenURI.replace('ipfs://', ''); + ipnft.metadata = ipfsLocation + ipnft.updatedAtTimestamp = event.block.timestamp + IpnftMetadataTemplate.create(ipfsLocation) + store.remove('Reservation', event.params.tokenId.toString()) ipnft.save() + } export function handleMetadataUpdated(event: MetadataUpdateEvent): void { @@ -94,8 +101,19 @@ export function handleMetadataUpdated(event: MetadataUpdateEvent): void { //erc4906 is not emitting the new url, we must query it ourselves let _ipnftContract = IPNFTContract.bind(event.params._event.address); let newUri = _ipnftContract.tokenURI(event.params._tokenId) + if (!newUri) { + log.debug("no new uri found for token, likely just minted {}", [event.params._tokenId.toString()]) + return + } ipnft.tokenURI = newUri + + let ipfsLocation = newUri.replace('ipfs://', ''); + ipnft.updatedAtTimestamp = event.block.timestamp + ipnft.metadata = ipfsLocation + + IpnftMetadataTemplate.create(ipfsLocation) + ipnft.save() } diff --git a/subgraph/src/metadataMapping.ts b/subgraph/src/metadataMapping.ts new file mode 100644 index 00000000..10468e50 --- /dev/null +++ b/subgraph/src/metadataMapping.ts @@ -0,0 +1,22 @@ +import { json, Bytes, dataSource } from '@graphprotocol/graph-ts' +import { IpnftMetadata } from '../generated/schema' + +export function handleMetadata(content: Bytes): void { + let ipnftMetadata = new IpnftMetadata(dataSource.stringParam()) + const value = json.fromBytes(content).toObject() + if (value) { + const image = value.get('image') + const name = value.get('name') + const description = value.get('description') + const externalURL = value.get('external_url') + + if (name && image && description && externalURL) { + ipnftMetadata.name = name.toString() + ipnftMetadata.image = image.toString() + ipnftMetadata.externalURL = externalURL.toString() + ipnftMetadata.description = description.toString() + } + + ipnftMetadata.save() + } +} \ No newline at end of file diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 89d2eb5e..14713803 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -228,3 +228,16 @@ templates: handler: handleScheduled - event: ScheduleReleased(indexed bytes32,indexed address,uint256) handler: handleReleased + - name: IpnftMetadata + kind: file/ipfs + mapping: + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/metadataMapping.ts + handler: handleMetadata + entities: + - IpnftMetadata + abis: + - name: IPNFT + file: ./abis/IPNFT.json + network: foundry