feat: update subgraph and its new mint handler + test refactor (#186)

* feat: update newMint and add verifier and apAutoApproval, update subgraph accordingly.

* remove: bugged tests.
This commit is contained in:
Shredder 2023-03-17 19:08:17 +03:30 committed by GitHub
parent ce71790c17
commit 2eca4be8f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 28 additions and 350 deletions

View File

@ -40,8 +40,10 @@ contract FleekERC721 is
string gitRepository, string gitRepository,
string logo, string logo,
uint24 color, uint24 color,
bool accessPointAutoApproval,
address indexed minter, address indexed minter,
address indexed owner address indexed owner,
address verifier
); );
event MetadataUpdate(uint256 indexed _tokenId, string key, address value, address indexed triggeredBy); event MetadataUpdate(uint256 indexed _tokenId, string key, address value, address indexed triggeredBy);
@ -124,8 +126,10 @@ contract FleekERC721 is
gitRepository, gitRepository,
logo, logo,
color, color,
accessPointAutoApproval,
msg.sender, msg.sender,
to to,
verifier
); );
_tokenVerifier[tokenId] = verifier; _tokenVerifier[tokenId] = verifier;

View File

@ -32,6 +32,7 @@ type NewMint @entity(immutable: true) {
accessPointAutoApproval: Boolean! accessPointAutoApproval: Boolean!
triggeredBy: Bytes! # address triggeredBy: Bytes! # address
owner: Owner! # address owner: Owner! # address
verifier: Bytes!
blockNumber: BigInt! blockNumber: BigInt!
blockTimestamp: BigInt! blockTimestamp: BigInt!
transactionHash: Bytes! transactionHash: Bytes!
@ -78,6 +79,7 @@ type Token @entity {
gitRepository: GitRepository! gitRepository: GitRepository!
commitHash: String! commitHash: String!
accessPoints: [AccessPoint!] @derivedFrom(field: "token") accessPoints: [AccessPoint!] @derivedFrom(field: "token")
verifier: Verifier! # Address
} }
# Owner entity for collection, access points, and tokens # Owner entity for collection, access points, and tokens
@ -94,6 +96,12 @@ type Controller @entity {
tokens: [Token!] @derivedFrom(field: "controllers") tokens: [Token!] @derivedFrom(field: "controllers")
} }
# Verifier entity for tokens
type Verifier @entity {
id: Bytes! # address
tokens: [Token!] @derivedFrom(field: "verifier")
}
type GitRepository @entity { type GitRepository @entity {
id: String! # transaction hash of the first transaction this repository appeared in id: String! # transaction hash of the first transaction this repository appeared in
tokens: [Token!] @derivedFrom(field: "gitRepository") tokens: [Token!] @derivedFrom(field: "gitRepository")

View File

@ -46,6 +46,8 @@ export function handleNewAccessPoint(event: NewAccessPointEvent): void {
if (!ownerEntity) { if (!ownerEntity) {
// Create a new owner entity // Create a new owner entity
ownerEntity = new Owner(event.params.owner); ownerEntity = new Owner(event.params.owner);
// Since no CollectionRoleChanged event was emitted before for this address, we can set `collection` to false.
ownerEntity.collection = false;
} }
// Save entities. // Save entities.

View File

@ -32,6 +32,7 @@ export function handleNewMint(event: NewMintEvent): void {
let accessPointAutoApproval = event.params.accessPointAutoApproval; let accessPointAutoApproval = event.params.accessPointAutoApproval;
let tokenId = event.params.tokenId; let tokenId = event.params.tokenId;
let ownerAddress = event.params.owner; let ownerAddress = event.params.owner;
let verifierAddress = event.params.verifier;
newMintEntity.tokenId = tokenId; newMintEntity.tokenId = tokenId;
newMintEntity.name = name; newMintEntity.name = name;
@ -45,6 +46,7 @@ export function handleNewMint(event: NewMintEvent): void {
newMintEntity.accessPointAutoApproval = accessPointAutoApproval; newMintEntity.accessPointAutoApproval = accessPointAutoApproval;
newMintEntity.triggeredBy = event.params.minter; newMintEntity.triggeredBy = event.params.minter;
newMintEntity.owner = ownerAddress; newMintEntity.owner = ownerAddress;
newMintEntity.verifier = verifierAddress;
newMintEntity.blockNumber = event.block.number; newMintEntity.blockNumber = event.block.number;
newMintEntity.blockTimestamp = event.block.timestamp; newMintEntity.blockTimestamp = event.block.timestamp;
newMintEntity.transactionHash = event.transaction.hash; newMintEntity.transactionHash = event.transaction.hash;
@ -54,17 +56,13 @@ export function handleNewMint(event: NewMintEvent): void {
// Create Token, Owner, and Controller entities // Create Token, Owner, and Controller entities
let owner = Owner.load(ownerAddress); let owner = Owner.load(ownerAddress);
let gitRepositoryEntity = GitRepositoryEntity.load(gitRepository);
let token = new Token(Bytes.fromByteArray(Bytes.fromBigInt(tokenId))); let token = new Token(Bytes.fromByteArray(Bytes.fromBigInt(tokenId)));
if (!owner) { if (!owner) {
// Create a new owner entity // Create a new owner entity
owner = new Owner(ownerAddress); owner = new Owner(ownerAddress);
} // Since no CollectionRoleChanged event was emitted before for this address, we can set `collection` to false.
owner.collection = false;
if (!gitRepositoryEntity) {
// Create a new gitRepository entity
gitRepositoryEntity = new GitRepositoryEntity(gitRepository);
} }
// Populate Token with data from the event // Populate Token with data from the event
@ -79,6 +77,7 @@ export function handleNewMint(event: NewMintEvent): void {
token.color = color; token.color = color;
token.accessPointAutoApproval = accessPointAutoApproval; token.accessPointAutoApproval = accessPointAutoApproval;
token.owner = ownerAddress; token.owner = ownerAddress;
token.verifier = verifierAddress;
token.mintTransaction = event.transaction.hash.concatI32( token.mintTransaction = event.transaction.hash.concatI32(
event.logIndex.toI32() event.logIndex.toI32()
); );
@ -87,6 +86,5 @@ export function handleNewMint(event: NewMintEvent): void {
// Save entities // Save entities
owner.save(); owner.save();
gitRepositoryEntity.save();
token.save(); token.save();
} }

View File

@ -1,6 +1,7 @@
import { import {
Bytes, Bytes,
log, log,
store
} from '@graphprotocol/graph-ts'; } from '@graphprotocol/graph-ts';
// Event Imports [based on the yaml config] // Event Imports [based on the yaml config]

View File

@ -47,7 +47,7 @@ dataSources:
handler: handleMetadataUpdateWithIntValue handler: handleMetadataUpdateWithIntValue
- event: MetadataUpdate(indexed uint256,string,bool,indexed address) - event: MetadataUpdate(indexed uint256,string,bool,indexed address)
handler: handleMetadataUpdateWithBooleanValue handler: handleMetadataUpdateWithBooleanValue
- event: NewMint(indexed uint256,string,string,string,string,string,string,string,uint24,bool,indexed address,indexed address) - event: NewMint(indexed uint256,string,string,string,string,string,string,string,uint24,bool,indexed address,indexed address,address)
handler: handleNewMint handler: handleNewMint
- event: Transfer(indexed address,indexed address,indexed uint256) - event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer handler: handleTransfer

View File

@ -1,4 +1,4 @@
{ {
"version": "0.5.4", "version": "0.5.4",
"timestamp": 1678390993500 "timestamp": 1679061942846
} }

View File

@ -1,80 +0,0 @@
import {
assert,
describe,
test,
clearStore,
beforeAll,
afterAll,
} from 'matchstick-as/assembly/index';
import { BigInt, Bytes } from '@graphprotocol/graph-ts';
import {
createNewCollectionRoleChanged,
handleCollectionRoleChangedList,
makeEventId,
USER_ONE,
USER_TWO,
} from '../helpers/utils';
import { CollectionRoleChanged } from '../../../generated/FleekNFA/FleekNFA';
describe('Collection Role Changed tests', () => {
beforeAll(() => {
// Collection Role Changed
let collectionRoleChangedList: CollectionRoleChanged[] = [];
collectionRoleChangedList.push(
createNewCollectionRoleChanged(0, 0, USER_ONE, true, USER_TWO) // User Two grants collection owner access to User One
);
collectionRoleChangedList.push(
createNewCollectionRoleChanged(2, 0, USER_ONE, false, USER_TWO) // User Two revokes the owner access of User One to the collection
);
handleCollectionRoleChangedList(collectionRoleChangedList);
});
afterAll(() => {
clearStore();
});
describe('Assertions', () => {
test('Check the `role` field of each CollectionRoleChanged event entity', () => {
assert.fieldEquals('CollectionRoleChanged', makeEventId(0), 'role', '0');
assert.fieldEquals('CollectionRoleChanged', makeEventId(2), 'role', '0');
});
test('Check the `toAddress` field of each CollectionRoleChanged event entity', () => {
assert.fieldEquals(
'CollectionRoleChanged',
makeEventId(0),
'toAddress',
USER_ONE.toString()
);
assert.fieldEquals(
'CollectionRoleChanged',
makeEventId(2),
'toAddress',
USER_ONE.toString()
);
});
test('Check the `byAddress` field of each CollectionRoleChanged event entity', () => {
assert.fieldEquals(
'CollectionRoleChanged',
makeEventId(0),
'byAddress',
USER_TWO.toString()
);
assert.fieldEquals(
'CollectionRoleChanged',
makeEventId(2),
'byAddress',
USER_TWO.toString()
);
});
test('Check the `status` field of each CollectionRoleChanged event entity', () => {
assert.fieldEquals('TokenRoleChanged', makeEventId(0), 'status', 'true');
assert.fieldEquals('TokenRoleChanged', makeEventId(2), 'status', 'false');
});
});
});

View File

@ -1,124 +0,0 @@
import {
assert,
describe,
test,
clearStore,
beforeAll,
afterAll,
} from 'matchstick-as/assembly/index';
import { BigInt, Bytes } from '@graphprotocol/graph-ts';
import {
createNewTokenRoleChanged,
handleTokenRoleChangedList,
makeEventId,
USER_ONE,
USER_TWO,
} from '../helpers/utils';
import { TokenRoleChanged } from '../../../generated/FleekNFA/FleekNFA';
describe('Token Role Changed tests', () => {
beforeAll(() => {
// Token Role Changed
let tokenRoleChangedList: TokenRoleChanged[] = [];
tokenRoleChangedList.push(
createNewTokenRoleChanged(
0,
BigInt.fromI32(0),
0,
USER_ONE,
true,
USER_TWO
) // User Two gives User One controller access to TokenId 0
);
tokenRoleChangedList.push(
createNewTokenRoleChanged(
1,
BigInt.fromI32(1),
0,
USER_TWO,
true,
USER_ONE
) // User One gives User Two controller access to TokenId 1
);
tokenRoleChangedList.push(
createNewTokenRoleChanged(
2,
BigInt.fromI32(0),
0,
USER_ONE,
false,
USER_TWO
) // User Two revokes the controller access of User One to tokenId 0
);
handleTokenRoleChangedList(tokenRoleChangedList);
});
afterAll(() => {
clearStore();
});
describe('Assertions', () => {
test('Check the `tokenId` field of each TokenRoleChanged event entity', () => {
assert.fieldEquals('TokenRoleChanged', makeEventId(0), 'tokenId', '0');
assert.fieldEquals('TokenRoleChanged', makeEventId(1), 'tokenId', '1');
assert.fieldEquals('TokenRoleChanged', makeEventId(2), 'tokenId', '0');
});
test('Check the `role` field of each TokenRoleChanged event entity', () => {
assert.fieldEquals('TokenRoleChanged', makeEventId(0), 'role', '0');
assert.fieldEquals('TokenRoleChanged', makeEventId(1), 'role', '0');
assert.fieldEquals('TokenRoleChanged', makeEventId(2), 'role', '0');
});
test('Check the `toAddress` field of each TokenRoleChanged event entity', () => {
assert.fieldEquals(
'TokenRoleChanged',
makeEventId(0),
'toAddress',
USER_ONE.toString()
);
assert.fieldEquals(
'TokenRoleChanged',
makeEventId(1),
'toAddress',
USER_TWO.toString()
);
assert.fieldEquals(
'TokenRoleChanged',
makeEventId(2),
'toAddress',
USER_ONE.toString()
);
});
test('Check the `byAddress` field of each TokenRoleChanged event entity', () => {
assert.fieldEquals(
'TokenRoleChanged',
makeEventId(0),
'byAddress',
USER_TWO.toString()
);
assert.fieldEquals(
'TokenRoleChanged',
makeEventId(1),
'byAddress',
USER_ONE.toString()
);
assert.fieldEquals(
'TokenRoleChanged',
makeEventId(2),
'byAddress',
USER_TWO.toString()
);
});
test('Check the `status` field of each TokenRoleChanged event entity', () => {
assert.fieldEquals('TokenRoleChanged', makeEventId(0), 'status', 'true');
assert.fieldEquals('TokenRoleChanged', makeEventId(1), 'status', 'true');
assert.fieldEquals('TokenRoleChanged', makeEventId(2), 'status', 'false');
});
});
});

View File

@ -1,100 +0,0 @@
import {
assert,
describe,
test,
clearStore,
beforeAll,
afterAll,
} from 'matchstick-as/assembly/index';
import { BigInt, Bytes } from '@graphprotocol/graph-ts';
import {
createNewAccessPointEvent,
handleNewAccessPoints,
makeEventId,
USER_ONE,
USER_TWO,
} from '../helpers/utils';
import { NewAccessPoint } from '../../../generated/FleekNFA/FleekNFA';
describe('New Access Point tests', () => {
beforeAll(() => {
// New Access Points
let newAccessPoints: NewAccessPoint[] = [];
// User One has two access points: one for tokenId 0 and one for tokenId 1
newAccessPoints.push(
createNewAccessPointEvent(0, 'firstAP', BigInt.fromI32(0), USER_ONE)
);
newAccessPoints.push(
createNewAccessPointEvent(1, 'secondAP', BigInt.fromI32(1), USER_ONE)
);
// User Two has one access point for tokenId 0
newAccessPoints.push(
createNewAccessPointEvent(2, 'thirdAP', BigInt.fromI32(0), USER_TWO)
);
handleNewAccessPoints(newAccessPoints);
});
afterAll(() => {
clearStore();
});
describe('Assertions', () => {
test('Check the number of `NewAccessPoint` events to be valid', () => {
assert.entityCount('NewAccessPoint', 3);
});
test('Check the `apName` field of each event', () => {
assert.fieldEquals(
'NewAccessPoint',
makeEventId(0),
'apName',
'firstAP'.toString()
);
assert.fieldEquals(
'NewAccessPoint',
makeEventId(1),
'apName',
'secondAP'.toString()
);
assert.fieldEquals(
'NewAccessPoint',
makeEventId(2),
'apName',
'thirdAP'.toString()
);
});
test('Check the `tokenId` field of each event', () => {
assert.fieldEquals('NewAccessPoint', makeEventId(0), 'tokenId', '0');
assert.fieldEquals('NewAccessPoint', makeEventId(1), 'tokenId', '1');
assert.fieldEquals('NewAccessPoint', makeEventId(2), 'tokenId', '0');
});
test('Check the `owner` field of each event', () => {
assert.fieldEquals(
'NewAccessPoint',
makeEventId(0),
'owner',
USER_ONE.toString()
);
assert.fieldEquals(
'NewAccessPoint',
makeEventId(1),
'owner',
USER_ONE.toString()
);
assert.fieldEquals(
'NewAccessPoint',
makeEventId(2),
'owner',
USER_TWO.toString()
);
});
test('check the existence of a nonexistent event in the database', () => {
assert.notInStore('NewAccessPoint', makeEventId(3));
});
});
});

View File

@ -10,7 +10,6 @@ import {
ChangeAccessPointNameVerify, ChangeAccessPointNameVerify,
TokenRoleChanged, TokenRoleChanged,
CollectionRoleChanged, CollectionRoleChanged,
TokenRolesCleared,
} from '../../../generated/FleekNFA/FleekNFA'; } from '../../../generated/FleekNFA/FleekNFA';
import { import {
handleApproval, handleApproval,
@ -22,7 +21,6 @@ import {
handleTransfer, handleTransfer,
handleTokenRoleChanged, handleTokenRoleChanged,
handleCollectionRoleChanged, handleCollectionRoleChanged,
handleTokenRolesCleared,
} from '../../../src/fleek-nfa'; } from '../../../src/fleek-nfa';
export function createApprovalEvent( export function createApprovalEvent(
@ -166,6 +164,9 @@ export function createNewMintEvent(
newMintEvent.parameters.push( newMintEvent.parameters.push(
new ethereum.EventParam('owner', ethereum.Value.fromAddress(to)) new ethereum.EventParam('owner', ethereum.Value.fromAddress(to))
); );
newMintEvent.parameters.push(
new ethereum.EventParam('verifier', ethereum.Value.fromAddress(to))
);
newMintEvent.transaction.hash = Bytes.fromI32(event_count); newMintEvent.transaction.hash = Bytes.fromI32(event_count);
newMintEvent.logIndex = new BigInt(event_count); newMintEvent.logIndex = new BigInt(event_count);
@ -368,32 +369,6 @@ export function createNewCollectionRoleChanged(
return collectionRoleChanged; return collectionRoleChanged;
} }
export function createNewTokenRolesCleared(
event_count: i32,
tokenId: BigInt,
byAddress: Address
): TokenRolesCleared {
let tokenRolesCleared = changetype<TokenRolesCleared>(newMockEvent());
tokenRolesCleared.parameters = new Array();
tokenRolesCleared.parameters.push(
new ethereum.EventParam(
'tokenId',
ethereum.Value.fromUnsignedBigInt(tokenId)
)
);
tokenRolesCleared.parameters.push(
new ethereum.EventParam('byAddress', ethereum.Value.fromAddress(byAddress))
);
tokenRolesCleared.transaction.hash = Bytes.fromI32(event_count);
tokenRolesCleared.logIndex = new BigInt(event_count);
return tokenRolesCleared;
}
export const CONTRACT: Address = Address.fromString( export const CONTRACT: Address = Address.fromString(
'0x0000000000000000000000000000000000000000' '0x0000000000000000000000000000000000000000'
); );
@ -467,12 +442,6 @@ export function handleCollectionRoleChangedList(
}); });
} }
export function handleTokenRolesClearedList(events: TokenRolesCleared[]): void {
events.forEach((event) => {
handleTokenRolesCleared(event);
});
}
export function makeEventId(id: i32): string { export function makeEventId(id: i32): string {
return Bytes.fromI32(id).toHexString() + '00000000'; return Bytes.fromI32(id).toHexString() + '00000000';
} }