import { Address, Bytes, log, store, ethereum, BigInt, } from '@graphprotocol/graph-ts'; // Event Imports [based on the yaml config] import { Approval as ApprovalEvent, ApprovalForAll as ApprovalForAllEvent, MetadataUpdate as MetadataUpdateEvent, MetadataUpdate1 as MetadataUpdateEvent1, MetadataUpdate2 as MetadataUpdateEvent2, TokenRoleChanged as TokenRoleChangedEvent, MetadataUpdate3 as MetadataUpdateEvent3, CollectionRoleChanged as CollectionRoleChangedEvent, Initialized as InitializedEvent, Transfer as TransferEvent, NewMint as NewMintEvent, ChangeAccessPointCreationStatus as ChangeAccessPointCreationStatusEvent, ChangeAccessPointScore as ChangeAccessPointCreationScoreEvent, NewAccessPoint as NewAccessPointEvent, ChangeAccessPointNameVerify as ChangeAccessPointNameVerifyEvent, ChangeAccessPointContentVerify as ChangeAccessPointContentVerifyEvent, } from '../generated/FleekNFA/FleekNFA'; // Entity Imports [based on the schema] import { AccessPoint, Approval, ApprovalForAll, Owner, GitRepository as GitRepositoryEntity, MetadataUpdate, NewMint, Token, Transfer, } from '../generated/schema'; enum CollectionRoles { Owner, } enum TokenRoles { Controller, } export function handleApproval(event: ApprovalEvent): void { let entity = new Approval( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.owner = event.params.owner; entity.approved = event.params.approved; entity.tokenId = event.params.tokenId; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); } export function handleApprovalForAll(event: ApprovalForAllEvent): void { let entity = new ApprovalForAll( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.owner = event.params.owner; entity.operator = event.params.operator; entity.approved = event.params.approved; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); } export function handleNewMint(event: NewMintEvent): void { let newMintEntity = new NewMint( event.transaction.hash.concatI32(event.logIndex.toI32()) ); let name = event.params.name; let description = event.params.description; let externalURL = event.params.externalURL; let ENS = event.params.ENS; let gitRepository = event.params.gitRepository; let commitHash = event.params.commitHash; let logo = event.params.logo; let color = event.params.color; let accessPointAutoApproval = event.params.accessPointAutoApproval; let tokenId = event.params.tokenId; let ownerAddress = event.params.owner; newMintEntity.tokenId = tokenId; newMintEntity.name = name; newMintEntity.description = description; newMintEntity.externalURL = externalURL; newMintEntity.ENS = ENS; newMintEntity.commitHash = commitHash; newMintEntity.gitRepository = gitRepository; newMintEntity.logo = logo; newMintEntity.color = color; newMintEntity.accessPointAutoApproval = accessPointAutoApproval; newMintEntity.triggeredBy = event.params.minter; newMintEntity.owner = ownerAddress; newMintEntity.blockNumber = event.block.number; newMintEntity.blockTimestamp = event.block.timestamp; newMintEntity.transactionHash = event.transaction.hash; newMintEntity.save(); log.error('{}', [tokenId.toString()]); // Create Token, Owner, and Controller entities let owner = Owner.load(ownerAddress); let gitRepositoryEntity = GitRepositoryEntity.load(gitRepository); let token = new Token(Bytes.fromByteArray(Bytes.fromBigInt(tokenId))); if (!owner) { // Create a new owner entity owner = new Owner(ownerAddress); } if (!gitRepositoryEntity) { // Create a new gitRepository entity gitRepositoryEntity = new GitRepositoryEntity(gitRepository); } // Populate Token with data from the event token.tokenId = tokenId; token.name = name; token.description = description; token.externalURL = externalURL; token.ENS = ENS; token.gitRepository = gitRepository; token.commitHash = commitHash; token.logo = logo; token.color = color; token.accessPointAutoApproval = accessPointAutoApproval; token.owner = ownerAddress; token.mintTransaction = event.transaction.hash.concatI32( event.logIndex.toI32() ); token.mintedBy = event.params.minter; token.controllers = [ownerAddress]; // Save entities owner.save(); gitRepositoryEntity.save(); token.save(); } export function handleMetadataUpdateWithStringValue( event: MetadataUpdateEvent ): void { /** * Metadata handled here: * setTokenExternalURL * setTokenENS * setTokenName * setTokenDescription * setTokenLogo * */ let entity = new MetadataUpdate( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.tokenId = event.params._tokenId; entity.key = event.params.key; entity.stringValue = event.params.value; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); // UPDATE TOKEN let token = Token.load( Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)) ); if (token) { if (event.params.key == 'externalURL') { token.externalURL = event.params.value; } else if (event.params.key == 'ENS') { token.ENS = event.params.value; } else if (event.params.key == 'name') { token.name = event.params.value; } else if (event.params.key == 'description') { token.description = event.params.value; } else { // logo token.logo = event.params.value; } token.save(); } } export function handleMetadataUpdateWithDoubleStringValue( event: MetadataUpdateEvent2 ): void { /** * setTokenBuild */ let entity = new MetadataUpdate( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.key = event.params.key; entity.tokenId = event.params._tokenId; entity.doubleStringValue = event.params.value; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); // UPDATE TOKEN let token = Token.load( Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)) ); if (token) { if (event.params.key == 'build') { let gitRepositoryEntity = GitRepositoryEntity.load(event.params.value[1]); if (!gitRepositoryEntity) { // Create a new gitRepository entity gitRepositoryEntity = new GitRepositoryEntity(event.params.value[1]); } token.commitHash = event.params.value[0]; token.gitRepository = event.params.value[1]; token.save(); gitRepositoryEntity.save(); } } } export function handleMetadataUpdateWithIntValue( event: MetadataUpdateEvent1 ): void { /** * setTokenColor */ let entity = new MetadataUpdate( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.key = event.params.key; entity.tokenId = event.params._tokenId; entity.uint24Value = event.params.value; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); let token = Token.load( Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)) ); if (token) { if (event.params.key == 'color') { token.color = event.params.value; } token.save(); } } export function handleInitialized(event: InitializedEvent): void { // This is the contract creation transaction. log.warning('This is the contract creation transaction.', []); if (event.receipt) { let receipt = event.receipt as ethereum.TransactionReceipt; log.warning('Contract address is: {}', [ receipt.contractAddress.toHexString(), ]); // add owner let owner = new Owner(event.transaction.from); owner.collection = true; owner.save(); } } export function handleCollectionRoleChanged( event: CollectionRoleChangedEvent ): void { let toAddress = event.params.toAddress; let byAddress = event.params.byAddress; let role = event.params.role; let status = event.params.status; if (role === CollectionRoles.Owner) { // Owner role if (status) { // granted let owner = Owner.load(toAddress); if (!owner) { owner = new Owner(toAddress); } owner.collection = true; owner.save(); } else { // revoked let owner = Owner.load(toAddress); if (!owner) { log.error( 'Owner entity not found. Role: {}, byAddress: {}, toAddress: {}', [role.toString(), byAddress.toHexString(), toAddress.toHexString()] ); return; } owner.collection = false; owner.save(); } } else { log.error('Role not supported. Role: {}, byAddress: {}, toAddress: {}', [ role.toString(), byAddress.toHexString(), toAddress.toHexString(), ]); } } export function handleTokenRoleChanged(event: TokenRoleChangedEvent): void { let tokenId = event.params.tokenId; let toAddress = event.params.toAddress; let byAddress = event.params.byAddress; let role = event.params.role; let status = event.params.status; // load token let token = Token.load(Bytes.fromByteArray(Bytes.fromBigInt(tokenId))); if (!token) { log.error('Token not found. TokenId: {}', [tokenId.toString()]); return; } if (role === TokenRoles.Controller) { // Controller role // get the list of controllers. let token_controllers = token.controllers; if (!token_controllers) { token_controllers = []; } if (status) { // granted token_controllers.push(toAddress); } else { // revoked // remove address from the controllers list const index = token_controllers.indexOf(event.params.toAddress, 0); if (index > -1) { token_controllers.splice(index, 1); } } token.controllers = token_controllers; } else { log.error('Role not supported. Role: {}, byAddress: {}, toAddress: {}', [ role.toString(), byAddress.toHexString(), toAddress.toHexString(), ]); } } export function handleMetadataUpdateWithBooleanValue( event: MetadataUpdateEvent3 ): void { /** * accessPointAutoApproval */ let entity = new MetadataUpdate( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.key = event.params.key; entity.tokenId = event.params._tokenId; entity.booleanValue = event.params.value; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); let token = Token.load( Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)) ); if (token) { if (event.params.key == 'accessPointAutoApproval') { token.accessPointAutoApproval = event.params.value; } token.save(); } } export function handleTransfer(event: TransferEvent): void { let entity = new Transfer( event.transaction.hash.concatI32(event.logIndex.toI32()) ); entity.from = event.params.from; entity.to = event.params.to; entity.tokenId = event.params.tokenId; entity.blockNumber = event.block.number; entity.blockTimestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; entity.save(); let token: Token | null; let owner_address = event.params.to; let owner = Owner.load(owner_address); if (!owner) { // Create a new owner entity owner = new Owner(owner_address); } if (parseInt(event.params.from.toHexString()) !== 0) { // Transfer // Load the Token by using its TokenId token = Token.load( Bytes.fromByteArray(Bytes.fromBigInt(event.params.tokenId)) ); if (token) { // Entity exists token.owner = owner_address; // Save both entities owner.save(); token.save(); } else { // Entity does not exist log.error('Unknown token was transferred.', []); } } } /** * This handler will create and load entities in the following order: * - AccessPoint [create] * - Owner [load / create] * Note to discuss later: Should a `NewAccessPoint` entity be also created and defined? */ export function handleNewAccessPoint(event: NewAccessPointEvent): void { // Create an AccessPoint entity let accessPointEntity = new AccessPoint(event.params.apName); accessPointEntity.score = BigInt.fromU32(0); accessPointEntity.contentVerified = false; accessPointEntity.nameVerified = false; accessPointEntity.creationStatus = 'DRAFT'; // Since a `ChangeAccessPointCreationStatus` event is emitted instantly after `NewAccessPoint`, the status will be updated in that handler. accessPointEntity.owner = event.params.owner; accessPointEntity.token = Bytes.fromByteArray( Bytes.fromBigInt(event.params.tokenId) ); // Load / Create an Owner entity let ownerEntity = Owner.load(event.params.owner); if (!ownerEntity) { // Create a new owner entity ownerEntity = new Owner(event.params.owner); } // Save entities. accessPointEntity.save(); ownerEntity.save(); } /** * This handler will update the status of an access point entity. */ export function handleChangeAccessPointCreationStatus( event: ChangeAccessPointCreationStatusEvent ): void { // Load the AccessPoint entity let accessPointEntity = AccessPoint.load(event.params.apName); let status = event.params.status; if (accessPointEntity) { switch (status) { case 0: accessPointEntity.creationStatus = 'DRAFT'; break; case 1: accessPointEntity.creationStatus = 'APPROVED'; break; case 2: accessPointEntity.creationStatus = 'REJECTED'; break; case 3: accessPointEntity.creationStatus = 'REMOVED'; break; default: // Unknown status log.error( 'Unable to handle ChangeAccessPointCreationStatus. Unknown status. Status: {}, AccessPoint: {}', [status.toString(), event.params.apName] ); } accessPointEntity.save(); } else { // Unknown access point log.error( 'Unable to handle ChangeAccessPointCreationStatus. Unknown access point. Status: {}, AccessPoint: {}', [status.toString(), event.params.apName] ); } } /** * This handler will update the score of an access point entity. */ export function handleChangeAccessPointScore( event: ChangeAccessPointCreationScoreEvent ): void { // Load the AccessPoint entity let accessPointEntity = AccessPoint.load(event.params.apName); if (accessPointEntity) { accessPointEntity.score = event.params.score; accessPointEntity.save(); } else { // Unknown access point log.error( 'Unable to handle ChangeAccessPointScore. Unknown access point. Score: {}, AccessPoint: {}', [event.params.score.toString(), event.params.apName] ); } } /** * This handler will update the nameVerified field of an access point entity. */ export function handleChangeAccessPointNameVerify( event: ChangeAccessPointNameVerifyEvent ): void { // Load the AccessPoint entity let accessPointEntity = AccessPoint.load(event.params.apName); if (accessPointEntity) { accessPointEntity.nameVerified = event.params.verified; accessPointEntity.save(); } else { // Unknown access point log.error( 'Unable to handle ChangeAccessPointNameVerify. Unknown access point. Verified: {}, AccessPoint: {}', [event.params.verified.toString(), event.params.apName] ); } } /** * This handler will update the contentVerified field of an access point entity. */ export function handleChangeAccessPointContentVerify( event: ChangeAccessPointContentVerifyEvent ): void { // Load the AccessPoint entity let accessPointEntity = AccessPoint.load(event.params.apName); if (accessPointEntity) { accessPointEntity.contentVerified = event.params.verified; accessPointEntity.save(); } else { // Unknown access point log.error( 'Unable to handle ChangeAccessPointContentVerify. Unknown access point. Verified: {}, AccessPoint: {}', [event.params.verified.toString(), event.params.apName] ); } }