Skip to content

Commit

Permalink
Merge pull request #6 from OriumNetwork/feature--role-assignments
Browse files Browse the repository at this point in the history
Feature  role assignments
  • Loading branch information
karacurt committed Oct 23, 2023
2 parents e865e40 + e87422c commit d545cf1
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 138 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 15 additions & 6 deletions schema.graphql
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
type Nft @entity {
id: ID! # tokenId + tokenAddress
address: String!
tokenAddress: String!
tokenId: BigInt!
owner: Account!
rolesHistory: [Role!] @derivedFrom(field: "nft")
roles: [Role!] @derivedFrom(field: "nft")
}

type Account @entity {
id: ID! # address
nfts: [Nft!] @derivedFrom(field: "owner")
rolesGranted: [Role!] @derivedFrom(field: "grantor")
rolesReceived: [Role!] @derivedFrom(field: "grantee")
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!
createdAt: BigInt!
updatedAt: BigInt!
}

type Role @entity {
id: ID! # tokenId + tokenAddress + roleHash
roleHash: Bytes!
nft: Nft!
roleAssignments: [RoleAssignment!] @derivedFrom(field: "role")
}

type RoleApproval @entity {
Expand Down
10 changes: 7 additions & 3 deletions src/erc7432/role/grant-handler.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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(),
])
}
26 changes: 15 additions & 11 deletions src/erc7432/role/revoke-handler.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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(),
])
}
4 changes: 2 additions & 2 deletions src/erc7432/role/role-approval-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
])
Expand Down
53 changes: 40 additions & 13 deletions src/utils/helper.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -15,7 +15,7 @@ export function findOrCreateAccount(id: string): Account {
export function createNft(id: string, contractAddress: string, tokenId: BigInt, owner: string): Nft {
const nft = new Nft(id)
nft.tokenId = tokenId
nft.address = contractAddress.toLowerCase()
nft.tokenAddress = contractAddress.toLowerCase()
nft.owner = owner.toLowerCase()
nft.save()
return nft
Expand All @@ -25,27 +25,54 @@ 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)
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.createdAt = event.block.timestamp
}

roleAssignment.expirationDate = event.params._expirationDate
roleAssignment.revocable = event.params._revocable
roleAssignment.data = event.params._data
roleAssignment.updatedAt = event.block.timestamp
roleAssignment.save()
return roleAssignment
}

export function findOrCreateRole(nft: Nft, roleHash: Bytes): Role {
const roleId = generateRoleId(nft, roleHash)
let role = Role.load(roleId)

if (!role) {
role = new Role(roleId)
role.roleId = event.params._role
role.roleHash = roleHash
role.nft = nft.id
role.grantor = grantor.id
role.grantee = grantee.id
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()
}
Expand Down
2 changes: 1 addition & 1 deletion subgraph-goerli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dataSources:
entities:
- Nft
- Account
- Role
- RoleAssignment
- RoleApproval
abis:
- name: ERC7432
Expand Down
2 changes: 1 addition & 1 deletion subgraph-mumbai.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dataSources:
entities:
- Nft
- Account
- Role
- RoleAssignment
- RoleApproval
abis:
- name: ERC7432
Expand Down
2 changes: 1 addition & 1 deletion subgraph-polygon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dataSources:
entities:
- Nft
- Account
- Role
- RoleAssignment
- RoleApproval
abis:
- name: ERC7432
Expand Down
6 changes: 3 additions & 3 deletions tests/erc721/transfer-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('ERC-721 Transfer Handler', () => {
assert.entityCount('Account', 1)

const _id = generateNftId(event.address.toHexString(), event.params.tokenId.toString())
assert.fieldEquals('Nft', _id, 'address', ZERO_ADDRESS)
assert.fieldEquals('Nft', _id, 'tokenAddress', ZERO_ADDRESS)
assert.fieldEquals('Nft', _id, 'tokenId', tokenId)
assert.fieldEquals('Nft', _id, 'owner', Addresses[1])
})
Expand All @@ -38,7 +38,7 @@ describe('ERC-721 Transfer Handler', () => {
assert.entityCount('Account', 2)

const _id = generateNftId(event.address.toHexString(), event.params.tokenId.toString())
assert.fieldEquals('Nft', _id, 'address', ZERO_ADDRESS)
assert.fieldEquals('Nft', _id, 'tokenAddress', ZERO_ADDRESS)
assert.fieldEquals('Nft', _id, 'tokenId', tokenId)
assert.fieldEquals('Nft', _id, 'owner', Addresses[2])
})
Expand All @@ -54,7 +54,7 @@ describe('ERC-721 Transfer Handler', () => {
assert.entityCount('Account', 2)

const _id = generateNftId(event.address.toHexString(), event.params.tokenId.toString())
assert.fieldEquals('Nft', _id, 'address', ZERO_ADDRESS)
assert.fieldEquals('Nft', _id, 'tokenAddress', ZERO_ADDRESS)
assert.fieldEquals('Nft', _id, 'tokenId', tokenId)
assert.fieldEquals('Nft', _id, 'owner', Addresses[2])
})
Expand Down
Loading

0 comments on commit d545cf1

Please sign in to comment.