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

View File

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

View File

@ -46,6 +46,8 @@ export function handleNewAccessPoint(event: NewAccessPointEvent): void {
if (!ownerEntity) {
// Create a new owner entity
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.

View File

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

View File

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

View File

@ -47,7 +47,7 @@ dataSources:
handler: handleMetadataUpdateWithIntValue
- event: MetadataUpdate(indexed uint256,string,bool,indexed address)
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
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer

View File

@ -1,4 +1,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,
TokenRoleChanged,
CollectionRoleChanged,
TokenRolesCleared,
} from '../../../generated/FleekNFA/FleekNFA';
import {
handleApproval,
@ -22,7 +21,6 @@ import {
handleTransfer,
handleTokenRoleChanged,
handleCollectionRoleChanged,
handleTokenRolesCleared,
} from '../../../src/fleek-nfa';
export function createApprovalEvent(
@ -166,6 +164,9 @@ export function createNewMintEvent(
newMintEvent.parameters.push(
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.logIndex = new BigInt(event_count);
@ -368,32 +369,6 @@ export function createNewCollectionRoleChanged(
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(
'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 {
return Bytes.fromI32(id).toHexString() + '00000000';
}