diff --git a/abis/ERC7432.json b/abis/ERC7432.json index 47f3b19..ebb3940 100644 --- a/abis/ERC7432.json +++ b/abis/ERC7432.json @@ -122,7 +122,7 @@ "components": [ { "internalType": "bytes32", - "name": "role", + "name": "roleassignment", "type": "bytes32" }, { @@ -172,7 +172,7 @@ "components": [ { "internalType": "bytes32", - "name": "role", + "name": "roleassignment", "type": "bytes32" }, { diff --git a/package-lock.json b/package-lock.json index 15988b4..e4b76f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "": { "name": "roles-subgraph", "version": "1.0.0", - "license": "MIT", + "license": "CC0-1.0", "dependencies": { "@graphprotocol/graph-cli": "^0.55.0" }, diff --git a/schema.graphql b/schema.graphql index 1b0cc16..3c63820 100644 --- a/schema.graphql +++ b/schema.graphql @@ -3,24 +3,33 @@ type Nft @entity { address: String! tokenId: BigInt! owner: Account! - rolesHistory: [Role!] @derivedFrom(field: "nft") + rolesHistory: [RoleAssignment!] @derivedFrom(field: "nft") } type Account @entity { id: ID! # address nfts: [Nft!] @derivedFrom(field: "owner") + rolesGranted: [RoleAssignment!] @derivedFrom(field: "grantor") + rolesReceived: [RoleAssignment!] @derivedFrom(field: "grantee") roleApprovals: [RoleApproval!] @derivedFrom(field: "grantor") } -type Role @entity { +type RoleAssignment @entity { id: ID! # grantorAddress + tokenId + tokenAddress + granteeAddress + roleHash - roleId: Bytes! + role: Role! nft: Nft! grantor: Account! grantee: Account! expirationDate: BigInt! revocable: Boolean! data: Bytes! + timestamp: BigInt! +} + +type Role @entity { + id: ID! # tokenId + tokenAddress + roleHash + roleHash: Bytes! + roleAssignments: [RoleAssignment!] @derivedFrom(field: "role") } type RoleApproval @entity { diff --git a/src/erc7432/role/grant-handler.ts b/src/erc7432/role/grant-handler.ts index bb9f498..f71db3d 100644 --- a/src/erc7432/role/grant-handler.ts +++ b/src/erc7432/role/grant-handler.ts @@ -1,7 +1,7 @@ import { log } from '@graphprotocol/graph-ts' import { RoleGranted } from '../../../generated/ERC7432-Immutable-Roles/ERC7432' import { Account, Nft } from '../../../generated/schema' -import { generateNftId, findOrCreateAccount, findOrCreateRole } from '../../utils/helper' +import { generateNftId, findOrCreateAccount, findOrCreateRoleAssignment } from '../../utils/helper' export function handleRoleGranted(event: RoleGranted): void { const tokenId = event.params._tokenId.toString() @@ -26,6 +26,10 @@ export function handleRoleGranted(event: RoleGranted): void { } const granteeAccount = findOrCreateAccount(event.params._grantee.toHex()) - const role = findOrCreateRole(event, grantorAccount, granteeAccount, nft) - log.warning('[handleRoleGranted] Role: {} NFT: {} Tx: {}', [role.id, nftId, event.transaction.hash.toHex()]) + const roleAssignment = findOrCreateRoleAssignment(event, grantorAccount, granteeAccount, nft) + log.warning('[handleRoleGranted] roleAssignment: {} NFT: {} Tx: {}', [ + roleAssignment.id, + nftId, + event.transaction.hash.toHex(), + ]) } diff --git a/src/erc7432/role/revoke-handler.ts b/src/erc7432/role/revoke-handler.ts index 71da0fe..bf368a1 100644 --- a/src/erc7432/role/revoke-handler.ts +++ b/src/erc7432/role/revoke-handler.ts @@ -1,7 +1,7 @@ import { log } from '@graphprotocol/graph-ts' import { RoleRevoked } from '../../../generated/ERC7432-Immutable-Roles/ERC7432' -import { Account, Nft, Role } from '../../../generated/schema' -import { generateNftId, generateRoleId } from '../../utils/helper' +import { Account, Nft, RoleAssignment } from '../../../generated/schema' +import { generateNftId, generateRoleAssignmentId } from '../../utils/helper' export function handleRoleRevoked(event: RoleRevoked): void { const tokenId = event.params._tokenId.toString() @@ -28,18 +28,22 @@ export function handleRoleRevoked(event: RoleRevoked): void { return } - const roleId = generateRoleId(revoker, grantee, nft, event.params._role) - const role = Role.load(roleId) - if (!role) { - log.warning('[handleRoleRevoked] Role {} does not exist, skipping...', [roleId]) + const roleAssignmentId = generateRoleAssignmentId(revoker, grantee, nft, event.params._role) + const roleassignment = RoleAssignment.load(roleAssignmentId) + if (!roleassignment) { + log.warning('[handleRoleRevoked] RoleAssignment {} does not exist, skipping...', [roleAssignmentId]) return } - if (event.block.timestamp > role.expirationDate) { - log.warning('[handleRoleRevoked] Role {} already expired, skipping...', [roleId]) + if (event.block.timestamp > roleassignment.expirationDate) { + log.warning('[handleRoleRevoked] RoleAssignment {} already expired, skipping...', [roleAssignmentId]) return } - role.expirationDate = event.block.timestamp - role.save() - log.warning('[handleRoleRevoked] Revoked Role: {} NFT: {} Tx: {}', [roleId, nftId, event.transaction.hash.toHex()]) + roleassignment.expirationDate = event.block.timestamp + roleassignment.save() + log.warning('[handleRoleRevoked] Revoked RoleAssignment: {} NFT: {} Tx: {}', [ + roleAssignmentId, + nftId, + event.transaction.hash.toHex(), + ]) } diff --git a/src/erc7432/role/role-approval-handler.ts b/src/erc7432/role/role-approval-handler.ts index 54490a5..7729ed3 100644 --- a/src/erc7432/role/role-approval-handler.ts +++ b/src/erc7432/role/role-approval-handler.ts @@ -18,14 +18,14 @@ export function handleRoleApprovalForAll(event: RoleApprovalForAll): void { if (isApproved) { const roleApproval = insertRoleApprovalIfNotExist(grantorAccount, operatorAccount, tokenAddress) - log.warning('[handleRoleApprovalForAll] Updated Role Approval: {} Tx: {}', [ + log.warning('[handleRoleApprovalForAll] Updated RoleAssignment Approval: {} Tx: {}', [ roleApproval.id, event.transaction.hash.toHex(), ]) } else { const roleApprovalId = generateRoleApprovalId(grantorAccount, operatorAccount, tokenAddress) deleteRoleApprovalIfExist(roleApprovalId) - log.warning('[handleRoleApprovalForAll] Removed Role Approval: {} Tx: {}', [ + log.warning('[handleRoleApprovalForAll] Removed RoleAssignment Approval: {} Tx: {}', [ roleApprovalId, event.transaction.hash.toHex(), ]) diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 2950412..5f283b8 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -1,5 +1,5 @@ import { BigInt, Bytes, store } from '@graphprotocol/graph-ts' -import { Account, Nft, Role, RoleApproval } from '../../generated/schema' +import { Account, Nft, Role, RoleApproval, RoleAssignment } from '../../generated/schema' import { RoleGranted } from '../../generated/ERC7432-Immutable-Roles/ERC7432' export function findOrCreateAccount(id: string): Account { @@ -25,27 +25,51 @@ export function generateNftId(tokenAddress: string, tokenId: string): string { return tokenAddress + '-' + tokenId } -export function generateRoleId(grantor: Account, grantee: Account, nft: Nft, role: Bytes): string { - return grantor.id + '-' + grantee.id + '-' + nft.id + '-' + role.toHex() +export function generateRoleAssignmentId(grantor: Account, grantee: Account, nft: Nft, roleAssignment: Bytes): string { + return grantor.id + '-' + grantee.id + '-' + nft.id + '-' + roleAssignment.toHex() } -export function findOrCreateRole(event: RoleGranted, grantor: Account, grantee: Account, nft: Nft): Role { - const roleId = generateRoleId(grantor, grantee, nft, event.params._role) - let role = Role.load(roleId) +export function findOrCreateRoleAssignment( + event: RoleGranted, + grantor: Account, + grantee: Account, + nft: Nft, +): RoleAssignment { + const roleAssignmentId = generateRoleAssignmentId(grantor, grantee, nft, event.params._role) + let roleAssignment = RoleAssignment.load(roleAssignmentId) + + if (!roleAssignment) { + roleAssignment = new RoleAssignment(roleAssignmentId) + roleAssignment.role = findOrCreateRole(nft, event.params._role).id + roleAssignment.nft = nft.id + roleAssignment.grantor = grantor.id + roleAssignment.grantee = grantee.id + } + + roleAssignment.expirationDate = event.params._expirationDate + roleAssignment.revocable = event.params._revocable + roleAssignment.data = event.params._data + roleAssignment.timestamp = event.block.timestamp + roleAssignment.save() + return roleAssignment +} + +export function findOrCreateRole(nft: Nft, roleHash: Bytes): Role { + let role = Role.load(generateRoleId(nft, roleHash)) + if (!role) { - role = new Role(roleId) - role.roleId = event.params._role - role.nft = nft.id - role.grantor = grantor.id - role.grantee = grantee.id + role = new Role(generateRoleId(nft, roleHash)) + role.roleHash = roleHash + role.save() } - role.expirationDate = event.params._expirationDate - role.revocable = event.params._revocable - role.data = event.params._data - role.save() + return role } +export function generateRoleId(nft: Nft, roleHash: Bytes): string { + return nft.id + '-' + roleHash.toHex() +} + export function generateRoleApprovalId(grantor: Account, operator: Account, tokenAddress: string): string { return grantor.id + '-' + operator.id + '-' + tokenAddress.toLowerCase() } diff --git a/subgraph-goerli.yaml b/subgraph-goerli.yaml index 93e7eed..f5bd44b 100644 --- a/subgraph-goerli.yaml +++ b/subgraph-goerli.yaml @@ -38,7 +38,7 @@ dataSources: entities: - Nft - Account - - Role + - RoleAssignment - RoleApproval abis: - name: ERC7432 diff --git a/subgraph-mumbai.yaml b/subgraph-mumbai.yaml index 9dbb61a..6f506ea 100644 --- a/subgraph-mumbai.yaml +++ b/subgraph-mumbai.yaml @@ -18,7 +18,7 @@ dataSources: entities: - Nft - Account - - Role + - RoleAssignment - RoleApproval abis: - name: ERC7432 diff --git a/subgraph-polygon.yaml b/subgraph-polygon.yaml index 5661f9c..423c619 100644 --- a/subgraph-polygon.yaml +++ b/subgraph-polygon.yaml @@ -38,7 +38,7 @@ dataSources: entities: - Nft - Account - - Role + - RoleAssignment - RoleApproval abis: - name: ERC7432 diff --git a/tests/erc7432/grant-handler.test.ts b/tests/erc7432/grant-handler.test.ts index 7775630..45658c7 100644 --- a/tests/erc7432/grant-handler.test.ts +++ b/tests/erc7432/grant-handler.test.ts @@ -6,7 +6,7 @@ import { BigInt, Bytes } from '@graphprotocol/graph-ts' import { createMockAccount, createMockNft, validateRole } from '../helpers/entities' import { Account } from '../../generated/schema' -const RoleId = Bytes.fromUTF8('0xGrantRole') +const RoleAssignmentId = Bytes.fromUTF8('0xGrantRole') const tokenAddress = Addresses[0] const tokenId = '123' const grantee = Addresses[1] @@ -20,12 +20,12 @@ describe('ERC-7432 RoleGranted Handler', () => { clearStore() }) - test('should not grant role when NFT does not exist', () => { - assert.entityCount('Role', 0) + test('should not grant roleassignment when NFT does not exist', () => { + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 0) const event = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId, tokenAddress, grantee, @@ -36,17 +36,17 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 0) }) - test('should not grant role when grantor does not exist', () => { + test('should not grant roleassignment when grantor does not exist', () => { createMockNft(tokenAddress, tokenId, Addresses[0]) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 1) const event = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId, tokenAddress, grantee, @@ -57,18 +57,18 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 1) }) - test('should not grant role if grantor is not NFT owner', () => { + test('should not grant roleassignment if grantor is not NFT owner', () => { createMockNft(tokenAddress, tokenId, Addresses[0]) createMockAccount(grantor) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 2) const event = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId, tokenAddress, grantee, @@ -79,17 +79,17 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 2) }) test('should grant multiple roles for the same NFT', () => { const nft = createMockNft(tokenAddress, tokenId, grantor) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 1) const event1 = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId, tokenAddress, Addresses[0], @@ -100,7 +100,7 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event1) const event2 = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId, tokenAddress, Addresses[1], @@ -111,7 +111,7 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event2) const event3 = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId, tokenAddress, Addresses[2], @@ -122,13 +122,13 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event3) - assert.entityCount('Role', 3) + assert.entityCount('RoleAssignment', 3) assert.entityCount('Account', 3) const grantorAccount = new Account(grantor) - validateRole(grantorAccount, new Account(Addresses[0]), nft, RoleId, expirationDate, data) - validateRole(grantorAccount, new Account(Addresses[1]), nft, RoleId, expirationDate, data) - validateRole(grantorAccount, new Account(Addresses[2]), nft, RoleId, expirationDate, data) + validateRole(grantorAccount, new Account(Addresses[0]), nft, RoleAssignmentId, expirationDate, data) + validateRole(grantorAccount, new Account(Addresses[1]), nft, RoleAssignmentId, expirationDate, data) + validateRole(grantorAccount, new Account(Addresses[2]), nft, RoleAssignmentId, expirationDate, data) }) test('should grant multiple roles for different NFTs', () => { @@ -139,11 +139,11 @@ describe('ERC-7432 RoleGranted Handler', () => { const nft1 = createMockNft(tokenAddress, tokenId1, grantor) const nft2 = createMockNft(tokenAddress, tokenId2, grantor) const nft3 = createMockNft(tokenAddress, tokenId3, grantor) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) assert.entityCount('Account', 1) const event1 = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId1, tokenAddress, Addresses[0], @@ -154,7 +154,7 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event1) const event2 = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId2, tokenAddress, Addresses[1], @@ -165,7 +165,7 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event2) const event3 = createNewRoleGrantedEvent( - RoleId, + RoleAssignmentId, tokenId3, tokenAddress, Addresses[2], @@ -176,12 +176,12 @@ describe('ERC-7432 RoleGranted Handler', () => { ) handleRoleGranted(event3) - assert.entityCount('Role', 3) + assert.entityCount('RoleAssignment', 3) assert.entityCount('Account', 3) const grantorAccount = new Account(grantor) - validateRole(grantorAccount, new Account(Addresses[0]), nft1, RoleId, expirationDate, data) - validateRole(grantorAccount, new Account(Addresses[1]), nft2, RoleId, expirationDate, data) - validateRole(grantorAccount, new Account(Addresses[2]), nft3, RoleId, expirationDate, data) + validateRole(grantorAccount, new Account(Addresses[0]), nft1, RoleAssignmentId, expirationDate, data) + validateRole(grantorAccount, new Account(Addresses[1]), nft2, RoleAssignmentId, expirationDate, data) + validateRole(grantorAccount, new Account(Addresses[2]), nft3, RoleAssignmentId, expirationDate, data) }) }) diff --git a/tests/erc7432/revoke-handler.test.ts b/tests/erc7432/revoke-handler.test.ts index 2e9d364..e56aea0 100644 --- a/tests/erc7432/revoke-handler.test.ts +++ b/tests/erc7432/revoke-handler.test.ts @@ -2,13 +2,13 @@ import { assert, describe, test, clearStore, afterEach } from 'matchstick-as' import { createNewRoleRevokedEvent } from '../helpers/events' import { handleRoleRevoked } from '../../src/erc7432' import { Bytes, BigInt } from '@graphprotocol/graph-ts' -import { createMockAccount, createMockNft, createMockRole, validateRole } from '../helpers/entities' +import { createMockAccount, createMockNft, createMockRoleAssignment, validateRole } from '../helpers/entities' import { Addresses, ONE, TWO } from '../helpers/contants' -import { generateNftId, generateRoleId } from '../../src/utils/helper' +import { generateNftId, generateRoleAssignmentId } from '../../src/utils/helper' import { Account, Nft } from '../../generated/schema' const tokenId = '123' -const RoleId = Bytes.fromUTF8('0xGrantRole') +const RoleAssignmentId = Bytes.fromUTF8('0xGrantRole') const tokenAddress = Addresses[0] const grantee = Addresses[1] const revoker = Addresses[2] @@ -20,8 +20,8 @@ describe('ERC-7432 RoleRevoked Handler', () => { clearStore() }) - test('should not revoke role when NFT does not exist', () => { - assert.entityCount('Role', 0) + test('should not revoke roleassignment when NFT does not exist', () => { + assert.entityCount('RoleAssignment', 0) const nftId = generateNftId(tokenAddress, tokenId) const nft = new Nft(nftId) @@ -29,55 +29,55 @@ describe('ERC-7432 RoleRevoked Handler', () => { nft.tokenId = BigInt.fromString(tokenId) nft.owner = revoker - const event = createNewRoleRevokedEvent(RoleId, nft, revoker, grantee) + const event = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, grantee) handleRoleRevoked(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) }) - test('should not revoke role when revoker does not exist', () => { + test('should not revoke roleassignment when revoker does not exist', () => { const nft = createMockNft(tokenAddress, tokenId, Addresses[0]) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) - const event = createNewRoleRevokedEvent(RoleId, nft, revoker, grantee) + const event = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, grantee) handleRoleRevoked(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) }) - test('should not revoke role when grantee does not exist', () => { + test('should not revoke roleassignment when grantee does not exist', () => { const nft = createMockNft(tokenAddress, tokenId, revoker) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) - const event = createNewRoleRevokedEvent(RoleId, nft, revoker, grantee) + const event = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, grantee) handleRoleRevoked(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) }) - test('should not revoke role when role does not exist', () => { + test('should not revoke roleassignment when roleassignment does not exist', () => { const nft = createMockNft(tokenAddress, tokenId, revoker) createMockAccount(grantee) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) - const event = createNewRoleRevokedEvent(RoleId, nft, revoker, grantee) + const event = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, grantee) handleRoleRevoked(event) - assert.entityCount('Role', 0) + assert.entityCount('RoleAssignment', 0) }) - test('should not revoke role when role already expired', () => { + test('should not revoke roleassignment when roleassignment already expired', () => { const nft = createMockNft(tokenAddress, tokenId, revoker) const granteeAccount = createMockAccount(grantee) - createMockRole(RoleId, revoker, grantee, nft, BigInt.fromI32(0)) - assert.entityCount('Role', 1) + createMockRoleAssignment(RoleAssignmentId, revoker, grantee, nft, BigInt.fromI32(0)) + assert.entityCount('RoleAssignment', 1) - const event = createNewRoleRevokedEvent(RoleId, nft, revoker, grantee) + const event = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, grantee) handleRoleRevoked(event) - assert.entityCount('Role', 1) - const _id = generateRoleId(new Account(revoker), granteeAccount, nft, RoleId) - assert.fieldEquals('Role', _id, 'expirationDate', '0') + assert.entityCount('RoleAssignment', 1) + const _id = generateRoleAssignmentId(new Account(revoker), granteeAccount, nft, RoleAssignmentId) + assert.fieldEquals('RoleAssignment', _id, 'expirationDate', '0') }) test('should revoke multiple roles for the same NFT', () => { @@ -85,25 +85,25 @@ describe('ERC-7432 RoleRevoked Handler', () => { const account1 = createMockAccount(Addresses[0]) const account2 = createMockAccount(Addresses[1]) const account3 = createMockAccount(Addresses[2]) - createMockRole(RoleId, revoker, Addresses[0], nft, expirationDate) - createMockRole(RoleId, revoker, Addresses[1], nft, expirationDate.plus(ONE)) - createMockRole(RoleId, revoker, Addresses[2], nft, expirationDate.plus(TWO)) - assert.entityCount('Role', 3) + createMockRoleAssignment(RoleAssignmentId, revoker, Addresses[0], nft, expirationDate) + createMockRoleAssignment(RoleAssignmentId, revoker, Addresses[1], nft, expirationDate.plus(ONE)) + createMockRoleAssignment(RoleAssignmentId, revoker, Addresses[2], nft, expirationDate.plus(TWO)) + assert.entityCount('RoleAssignment', 3) - const event1 = createNewRoleRevokedEvent(RoleId, nft, revoker, Addresses[0]) + const event1 = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, Addresses[0]) handleRoleRevoked(event1) - const event2 = createNewRoleRevokedEvent(RoleId, nft, revoker, Addresses[1]) + const event2 = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, Addresses[1]) handleRoleRevoked(event2) - const event3 = createNewRoleRevokedEvent(RoleId, nft, revoker, Addresses[2]) + const event3 = createNewRoleRevokedEvent(RoleAssignmentId, nft, revoker, Addresses[2]) handleRoleRevoked(event3) - assert.entityCount('Role', 3) + assert.entityCount('RoleAssignment', 3) const revokerAccount = new Account(revoker) - validateRole(revokerAccount, account1, nft, RoleId, ONE, data) - validateRole(revokerAccount, account2, nft, RoleId, ONE, data) - validateRole(revokerAccount, account3, nft, RoleId, ONE, data) + validateRole(revokerAccount, account1, nft, RoleAssignmentId, ONE, data) + validateRole(revokerAccount, account2, nft, RoleAssignmentId, ONE, data) + validateRole(revokerAccount, account3, nft, RoleAssignmentId, ONE, data) }) test('should revoke multiple roles for different NFTs', () => { @@ -111,24 +111,24 @@ describe('ERC-7432 RoleRevoked Handler', () => { const nft1 = createMockNft(tokenAddress, '123', revoker) const nft2 = createMockNft(tokenAddress, '456', revoker) const nft3 = createMockNft(tokenAddress, '789', revoker) - createMockRole(RoleId, revoker, grantee, nft1, expirationDate) - createMockRole(RoleId, revoker, grantee, nft2, expirationDate.plus(ONE)) - createMockRole(RoleId, revoker, grantee, nft3, expirationDate.plus(TWO)) - assert.entityCount('Role', 3) + createMockRoleAssignment(RoleAssignmentId, revoker, grantee, nft1, expirationDate) + createMockRoleAssignment(RoleAssignmentId, revoker, grantee, nft2, expirationDate.plus(ONE)) + createMockRoleAssignment(RoleAssignmentId, revoker, grantee, nft3, expirationDate.plus(TWO)) + assert.entityCount('RoleAssignment', 3) - const event1 = createNewRoleRevokedEvent(RoleId, nft1, revoker, grantee) + const event1 = createNewRoleRevokedEvent(RoleAssignmentId, nft1, revoker, grantee) handleRoleRevoked(event1) - const event2 = createNewRoleRevokedEvent(RoleId, nft2, revoker, grantee) + const event2 = createNewRoleRevokedEvent(RoleAssignmentId, nft2, revoker, grantee) handleRoleRevoked(event2) - const event3 = createNewRoleRevokedEvent(RoleId, nft3, revoker, grantee) + const event3 = createNewRoleRevokedEvent(RoleAssignmentId, nft3, revoker, grantee) handleRoleRevoked(event3) - assert.entityCount('Role', 3) + assert.entityCount('RoleAssignment', 3) const revokerAccount = new Account(revoker) - validateRole(revokerAccount, granteeAccount, nft1, RoleId, ONE, data) - validateRole(revokerAccount, granteeAccount, nft2, RoleId, ONE, data) - validateRole(revokerAccount, granteeAccount, nft3, RoleId, ONE, data) + validateRole(revokerAccount, granteeAccount, nft1, RoleAssignmentId, ONE, data) + validateRole(revokerAccount, granteeAccount, nft2, RoleAssignmentId, ONE, data) + validateRole(revokerAccount, granteeAccount, nft3, RoleAssignmentId, ONE, data) }) }) diff --git a/tests/helpers/entities.ts b/tests/helpers/entities.ts index 5df1ca4..3101373 100644 --- a/tests/helpers/entities.ts +++ b/tests/helpers/entities.ts @@ -1,6 +1,6 @@ import { BigInt, Bytes } from '@graphprotocol/graph-ts' -import { Account, Nft, Role, RoleApproval } from '../../generated/schema' -import { generateNftId, generateRoleId, generateRoleApprovalId } from '../../src/utils/helper' +import { Account, Nft, RoleAssignment, RoleApproval } from '../../generated/schema' +import { generateNftId, generateRoleAssignmentId, generateRoleApprovalId } from '../../src/utils/helper' import { assert } from 'matchstick-as' export function createMockNft(tokenAddress: string, tokenId: string, ownerAddress: string): Nft { @@ -21,18 +21,25 @@ export function createMockAccount(ethAddress: string): Account { return account } -export function createMockRole(role: Bytes, grantor: string, grantee: string, nft: Nft, expirationDate: BigInt): Role { - const roleId = generateRoleId(new Account(grantor), new Account(grantee), nft, role) - const newRole = new Role(roleId) - newRole.roleId = role - newRole.nft = nft.id - newRole.grantor = grantor - newRole.grantee = grantee - newRole.expirationDate = expirationDate - newRole.revocable = true - newRole.data = Bytes.fromUTF8('data') - newRole.save() - return newRole +export function createMockRoleAssignment( + roleHash: Bytes, + grantor: string, + grantee: string, + nft: Nft, + expirationDate: BigInt, +): RoleAssignment { + const roleAssignmentId = generateRoleAssignmentId(new Account(grantor), new Account(grantee), nft, roleHash) + const newRoleAssignment = new RoleAssignment(roleAssignmentId) + newRoleAssignment.role = `${nft.id}-${roleHash.toHex()}` + newRoleAssignment.nft = nft.id + newRoleAssignment.grantor = grantor + newRoleAssignment.grantee = grantee + newRoleAssignment.expirationDate = expirationDate + newRoleAssignment.revocable = true + newRoleAssignment.data = Bytes.fromUTF8('data') + newRoleAssignment.timestamp = BigInt.fromI32(123) + newRoleAssignment.save() + return newRoleAssignment } export function createMockRoleApproval(grantor: string, operator: string, tokenAddress: string): RoleApproval { @@ -49,17 +56,17 @@ export function validateRole( grantor: Account, grantee: Account, nft: Nft, - role: Bytes, + roleAssignment: Bytes, expirationDate: BigInt, data: Bytes, ): void { - const _id = generateRoleId(grantor, grantee, nft, role) - assert.fieldEquals('Role', _id, 'roleId', role.toHex()) - assert.fieldEquals('Role', _id, 'nft', nft.id) - assert.fieldEquals('Role', _id, 'grantor', grantor.id) - assert.fieldEquals('Role', _id, 'grantee', grantee.id) - assert.fieldEquals('Role', _id, 'expirationDate', expirationDate.toString()) - assert.fieldEquals('Role', _id, 'data', data.toHex()) + const _id = generateRoleAssignmentId(grantor, grantee, nft, roleAssignment) + assert.fieldEquals('RoleAssignment', _id, 'role', `${nft.id}-${roleAssignment.toHex()}`) + assert.fieldEquals('RoleAssignment', _id, 'nft', nft.id) + assert.fieldEquals('RoleAssignment', _id, 'grantor', grantor.id) + assert.fieldEquals('RoleAssignment', _id, 'grantee', grantee.id) + assert.fieldEquals('RoleAssignment', _id, 'expirationDate', expirationDate.toString()) + assert.fieldEquals('RoleAssignment', _id, 'data', data.toHex()) } export function validateRoleApproval(grantor: string, operator: string, tokenAddress: string): void { diff --git a/tests/helpers/events.ts b/tests/helpers/events.ts index b12cdf1..954b5f9 100644 --- a/tests/helpers/events.ts +++ b/tests/helpers/events.ts @@ -14,10 +14,15 @@ export function createTransferEvent(from: string, to: string, tokenId: string, a return event } -export function createNewRoleRevokedEvent(role: Bytes, nft: Nft, revoker: string, grantee: string): RoleRevoked { +export function createNewRoleRevokedEvent( + roleassignment: Bytes, + nft: Nft, + revoker: string, + grantee: string, +): RoleRevoked { const event = changetype(newMockEvent()) event.parameters = new Array() - event.parameters.push(buildEventParamBytes('_role', role)) + event.parameters.push(buildEventParamBytes('_role', roleassignment)) event.parameters.push(buildEventParamAddress('_tokenAddress', nft.address)) event.parameters.push(buildEventParamUint('_tokenId', nft.tokenId)) event.parameters.push(buildEventParamAddress('_revoker', revoker)) @@ -26,7 +31,7 @@ export function createNewRoleRevokedEvent(role: Bytes, nft: Nft, revoker: string } export function createNewRoleGrantedEvent( - role: Bytes, + roleassignment: Bytes, tokenId: string, tokenAddress: string, grantee: string, @@ -37,7 +42,7 @@ export function createNewRoleGrantedEvent( ): RoleGranted { const event = changetype(newMockEvent()) event.parameters = new Array() - event.parameters.push(buildEventParamBytes('_role', role)) + event.parameters.push(buildEventParamBytes('_role', roleassignment)) event.parameters.push(buildEventParamAddress('_tokenAddress', tokenAddress)) event.parameters.push(buildEventParamUint('_tokenId', BigInt.fromString(tokenId))) event.parameters.push(buildEventParamAddress('_grantor', grantor))