feat: updating subgraph following the ACL refactor (#144)

* refactor: remove unavailable imports, remove outdated entities, add command to regenerate the compile and codegen.

* feat: add handler for initialized, tokenrolechanged and collectionrolechanged.

* refactor: remove the collection entity.

* refactor: implement zoruka's requested changes - best practice recommendations.
This commit is contained in:
Shredder 2023-03-06 22:57:22 +03:30 committed by GitHub
parent 7971ae8cc7
commit c8a63b8618
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 39 deletions

View File

@ -31,7 +31,7 @@ type NewMint @entity(immutable: true) {
color: Int!
accessPointAutoApproval: Boolean!
triggeredBy: Bytes! # address
tokenOwner: Owner! # address
owner: Owner! # address
blockNumber: BigInt!
blockTimestamp: BigInt!
transactionHash: Bytes!
@ -80,28 +80,19 @@ type Token @entity {
accessPoints: [AccessPoint!] @derivedFrom(field: "token")
}
# Owner entity for collection, access points, and tokens
type Owner @entity {
id: Bytes! # address
tokens: [Token!] @derivedFrom(field: "owner")
accessPoints: [AccessPoint!] @derivedFrom(field: "owner")
collection: Boolean!
}
# Controller entity for tokens
type Controller @entity {
id: Bytes! # address
tokens: [Token!] @derivedFrom(field: "controllers")
}
type Collection @entity {
id: Bytes! #address
deployer: Bytes! #address
transactionHash: Bytes! #transaction hash
owners: [CollectionOwner!]
}
type CollectionOwner @entity {
id: Bytes! # address
accessGrantedBy: Bytes! #address
transactionHash: Bytes!
}
type GitRepository @entity {
id: String! # transaction hash of the first transaction this repository appeared in

View File

@ -1,11 +1,16 @@
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,
@ -14,21 +19,28 @@ import {
ChangeAccessPointNameVerify as ChangeAccessPointNameVerifyEvent,
ChangeAccessPointContentVerify as ChangeAccessPointContentVerifyEvent,
} from '../generated/FleekNFA/FleekNFA';
// Entity Imports [based on the schema]
import {
AccessPoint,
Approval,
ApprovalForAll,
Collection,
CollectionOwner,
Controller,
Owner,
GitRepository as GitRepositoryEntity,
MetadataUpdate,
NewMint,
Owner,
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())
@ -87,7 +99,7 @@ export function handleNewMint(event: NewMintEvent): void {
newMintEntity.color = color;
newMintEntity.accessPointAutoApproval = accessPointAutoApproval;
newMintEntity.triggeredBy = event.params.minter;
newMintEntity.tokenOwner = ownerAddress;
newMintEntity.owner = ownerAddress;
newMintEntity.blockNumber = event.block.number;
newMintEntity.blockTimestamp = event.block.timestamp;
newMintEntity.transactionHash = event.transaction.hash;
@ -97,7 +109,6 @@ export function handleNewMint(event: NewMintEvent): void {
// Create Token, Owner, and Controller entities
let owner = Owner.load(ownerAddress);
let controller = Controller.load(ownerAddress);
let gitRepositoryEntity = GitRepositoryEntity.load(gitRepository);
let token = new Token(Bytes.fromByteArray(Bytes.fromBigInt(tokenId)));
@ -106,11 +117,6 @@ export function handleNewMint(event: NewMintEvent): void {
owner = new Owner(ownerAddress);
}
if (!controller) {
// Create a new controller entity
controller = new Controller(ownerAddress);
}
if (!gitRepositoryEntity) {
// Create a new gitRepository entity
gitRepositoryEntity = new GitRepositoryEntity(gitRepository);
@ -136,7 +142,6 @@ export function handleNewMint(event: NewMintEvent): void {
// Save entities
owner.save();
controller.save();
gitRepositoryEntity.save();
token.save();
}
@ -257,6 +262,91 @@ export function handleMetadataUpdateWithIntValue(
}
}
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
@ -343,7 +433,7 @@ export function handleTransfer(event: TransferEvent): void {
accessPointEntity.score = BigInt.fromU32(0);
accessPointEntity.contentVerified = false;
accessPointEntity.nameVerified = false;
accessPointEntity.status = 'DRAFT'; // Since a `ChangeAccessPointCreationStatus` event is emitted instantly after `NewAccessPoint`, the status will be updated in that handler.
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));
@ -369,18 +459,24 @@ export function handleChangeAccessPointCreationStatus(event: ChangeAccessPointCr
let status = event.params.status;
if (accessPointEntity) {
if (status == 0) {
accessPointEntity.status = 'DRAFT';
} else if (status == 1) {
accessPointEntity.status = 'APPROVED';
} else if (status == 2) {
accessPointEntity.status = 'REJECTED';
} else if (status == 3) {
accessPointEntity.status = 'REMOVED';
} else {
// Unknown status
log.error('Unable to handle ChangeAccessPointCreationStatus. Unknown status. Status: {}, AccessPoint: {}', [status.toString(), event.params.apName]);
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

View File

@ -19,9 +19,10 @@ dataSources:
- NewMint
- Transfer
- Token
- Owner
- Controller
- TokenOwner
- TokenController
- CollectionOwner
- Collection
- GithubRepository
- AccessPoint
- ChangeAccessPointCreationStatus
@ -49,6 +50,14 @@ dataSources:
handler: handleNewMint
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer
- event: TokenRoleChanged(indexed uint256,indexed uint8,indexed address,bool,address)
handler: handleTokenRoleChanged
- event: TokenRolesCleared(indexed uint256,address)
handler: handleTokenRolesCleared
- event: CollectionRoleChanged(indexed uint8,indexed address,bool,address)
handler: handleCollectionRoleChanged
- event: Initialized(uint8)
handler: handleInitialized
- event: ChangeAccessPointContentVerify(string,uint256,indexed bool,indexed address)
handler: handleChangeAccessPointContentVerify
- event: ChangeAccessPointNameVerify(string,uint256,indexed bool,indexed address)