diff --git a/package.json b/package.json index a409eb81d..7d2353865 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "**/@graphprotocol/graph-cli", "**/@graphprotocol/graph-cli/**", "**/matchstick-as", - "**/matchstick-as/**" + "**/matchstick-as/**", + "**/@aragon/osx-commons-subgraph", + "**/@aragon/osx-commons-subgraph/**" ] }, "scripts": { diff --git a/packages/subgraph/package.json b/packages/subgraph/package.json index a9cb0d5ef..56ea6e8b8 100644 --- a/packages/subgraph/package.json +++ b/packages/subgraph/package.json @@ -31,5 +31,8 @@ "mustache": "^4.2.0", "ts-morph": "^17.0.1", "typescript": "^4.9.5" + }, + "dependencies": { + "@aragon/osx-commons-subgraph": "^0.0.3" } } diff --git a/packages/subgraph/src/dao/dao_v1_0_0.ts b/packages/subgraph/src/dao/dao_v1_0_0.ts index 14d434d30..09ccd6a36 100644 --- a/packages/subgraph/src/dao/dao_v1_0_0.ts +++ b/packages/subgraph/src/dao/dao_v1_0_0.ts @@ -30,10 +30,17 @@ import { } from '../utils/tokens/erc1155'; import {handleNativeDeposit} from '../utils/tokens/eth'; import {handleAction, updateProposalWithFailureMap} from './utils'; +import { + generateDaoEntityId, + generatePermissionEntityId, + generateProposalEntityId, + generateStandardCallbackEntityId, + generateTransactionActionsProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {BigInt, Bytes, store} from '@graphprotocol/graph-ts'; export function handleMetadataSet(event: MetadataSet): void { - let daoId = event.address.toHexString(); + let daoId = generateDaoEntityId(event.address); let metadata = event.params.metadata.toString(); _handleMetadataSet(daoId, metadata); } @@ -76,16 +83,16 @@ export function handleCallbackReceived(event: CallbackReceived): void { } export function handleExecuted(event: Executed): void { - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromByteArray(event.params.callId) + ); // Not an effective solution, until each plugin has // its own subgraph separately. // If proposal found, update its failureMap. let wasUpdated = updateProposalWithFailureMap( - proposalId, + proposalEntityId, event.params.failureMap ); @@ -100,13 +107,14 @@ export function handleExecuted(event: Executed): void { // might be a case when 2 different tx might end up having the same // proposal ID which will cause overwrite. In case of plugins, // It's plugin's responsibility to pass unique callId per execute. - proposalId = proposalId - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); - let proposal = new TransactionActionsProposal(proposalId); - proposal.dao = event.address.toHexString(); + proposalEntityId = generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.logIndex + ); + + let proposal = new TransactionActionsProposal(proposalEntityId); + proposal.dao = generateDaoEntityId(event.address); proposal.createdAt = event.block.timestamp; proposal.endDate = event.block.timestamp; proposal.startDate = event.block.timestamp; @@ -123,7 +131,7 @@ export function handleExecuted(event: Executed): void { let actions = event.params.actions; for (let index = 0; index < actions.length; index++) { - handleAction(actions[index], proposalId, index, event); + handleAction(actions[index], proposalEntityId, index, event); } } @@ -159,19 +167,17 @@ export function handleNativeTokenDeposited(event: NativeTokenDeposited): void { } export function handleGranted(event: Granted): void { - const contractAddress = event.address.toHexString(); + const contractAddress = event.address; const where = event.params.where; const permissionId = event.params.permissionId; const who = event.params.who; - const permissionEntityId = [ + const permissionEntityId = generatePermissionEntityId( contractAddress, - permissionId.toHexString(), - where.toHexString(), - who.toHexString(), - ].join('_'); - - const daoAddress = contractAddress; + permissionId, + where, + who + ); // Permission let permissionEntity = Permission.load(permissionEntityId); @@ -183,24 +189,24 @@ export function handleGranted(event: Granted): void { permissionEntity.actor = event.params.here; permissionEntity.condition = event.params.condition; - permissionEntity.dao = daoAddress; + permissionEntity.dao = generateDaoEntityId(contractAddress); permissionEntity.save(); } } export function handleRevoked(event: Revoked): void { // permission - const contractAddress = event.address.toHexString(); + const contractAddress = event.address; const where = event.params.where; const permissionId = event.params.permissionId; const who = event.params.who; - const permissionEntityId = [ + const permissionEntityId = generatePermissionEntityId( contractAddress, - permissionId.toHexString(), - where.toHexString(), - who.toHexString(), - ].join('_'); + permissionId, + where, + who + ); let permissionEntity = Permission.load(permissionEntityId); if (permissionEntity) { @@ -209,7 +215,7 @@ export function handleRevoked(event: Revoked): void { } export function handleTrustedForwarderSet(event: TrustedForwarderSet): void { - let daoId = event.address.toHexString(); + let daoId = generateDaoEntityId(event.address); let entity = Dao.load(daoId); if (entity) { entity.trustedForwarder = event.params.forwarder; @@ -220,22 +226,25 @@ export function handleTrustedForwarderSet(event: TrustedForwarderSet): void { export function handleStandardCallbackRegistered( event: StandardCallbackRegistered ): void { - let daoId = event.address.toHexString(); - let entityId = `${daoId}_${event.params.interfaceId.toHexString()}`; + let daoAddress = event.address; + let interfaceId = event.params.interfaceId; + + let daoId = generateDaoEntityId(daoAddress); + let entityId = generateStandardCallbackEntityId(daoAddress, interfaceId); let entity = StandardCallback.load(entityId); if (!entity) { entity = new StandardCallback(entityId); entity.dao = daoId; } - entity.interfaceId = event.params.interfaceId; + entity.interfaceId = interfaceId; entity.callbackSelector = event.params.callbackSelector; entity.magicNumber = event.params.magicNumber; entity.save(); } export function handleNewURI(event: NewURI): void { - let daoId = event.address.toHexString(); - let entity = Dao.load(daoId); + let daoEntityId = generateDaoEntityId(event.address); + let entity = Dao.load(daoEntityId); if (entity) { entity.daoURI = event.params.daoURI; entity.save(); diff --git a/packages/subgraph/src/dao/dao_v1_3_0.ts b/packages/subgraph/src/dao/dao_v1_3_0.ts index b05775ed1..ed075809f 100644 --- a/packages/subgraph/src/dao/dao_v1_3_0.ts +++ b/packages/subgraph/src/dao/dao_v1_3_0.ts @@ -4,20 +4,29 @@ import { ExecutedActionsStruct, } from '../../generated/templates/DaoTemplateV1_3_0/DAO'; import {handleAction} from './utils'; +import { + generateDaoEntityId, + generateProposalEntityId, + generateTransactionActionsProposalEntityId, +} from '@aragon/osx-commons-subgraph'; +import {BigInt} from '@graphprotocol/graph-ts'; export function handleExecuted(event: Executed): void { - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromByteArray(event.params.callId) + ); - proposalId = proposalId - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); - let proposal = new TransactionActionsProposal(proposalId); - proposal.dao = event.address.toHexString(); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); + let proposal = new TransactionActionsProposal( + transactionActionsProposalEntityId + ); + proposal.dao = generateDaoEntityId(event.address); proposal.createdAt = event.block.timestamp; proposal.endDate = event.block.timestamp; proposal.startDate = event.block.timestamp; @@ -33,7 +42,7 @@ export function handleExecuted(event: Executed): void { for (let index = 0; index < actions.length; index++) { handleAction( actions[index], - proposalId, + transactionActionsProposalEntityId, index, event ); diff --git a/packages/subgraph/src/dao/utils.ts b/packages/subgraph/src/dao/utils.ts index d69257c15..a1d6e6fa6 100644 --- a/packages/subgraph/src/dao/utils.ts +++ b/packages/subgraph/src/dao/utils.ts @@ -23,6 +23,7 @@ import {handleERC20Action} from '../utils/tokens/erc20'; import {handleERC721Action} from '../utils/tokens/erc721'; import {handleERC1155Action} from '../utils/tokens/erc1155'; import {handleNativeAction} from '../utils/tokens/eth'; +import {generateDaoEntityId} from '@aragon/osx-commons-subgraph'; import {BigInt} from '@graphprotocol/graph-ts'; // AssemblyScript struggles having multiple return types. Due to this, @@ -104,7 +105,7 @@ function getOrCreateActionEntity< entity.value = action.value; entity.data = action.data; entity.proposal = proposalId; - entity.dao = event.address.toHexString(); + entity.dao = generateDaoEntityId(event.address); } return entity; diff --git a/packages/subgraph/src/packages/addresslist/addresslist-voting.ts b/packages/subgraph/src/packages/addresslist/addresslist-voting.ts index d7a806298..06a989a9e 100644 --- a/packages/subgraph/src/packages/addresslist/addresslist-voting.ts +++ b/packages/subgraph/src/packages/addresslist/addresslist-voting.ts @@ -15,7 +15,14 @@ import { VotingSettingsUpdated, } from '../../../generated/templates/AddresslistVoting/AddresslistVoting'; import {RATIO_BASE, VOTER_OPTIONS, VOTING_MODES} from '../../utils/constants'; -import {getProposalId} from '../../utils/proposals'; +import {generateMemberEntityId, generateVoteEntityId} from '../../utils/ids'; +import { + generateActionEntityId, + generateEntityIdFromAddress, + generatePermissionEntityId, + generatePluginEntityId, + generateProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {BigInt, dataSource, store} from '@graphprotocol/graph-ts'; export function handleProposalCreated(event: ProposalCreated): void { @@ -32,12 +39,13 @@ export function _handleProposalCreated( metadata: string ): void { let pluginAddress = event.address; + let pluginEntityId = generatePluginEntityId(pluginAddress); let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(pluginAddress, pluginProposalId); + let proposalId = generateProposalEntityId(pluginAddress, pluginProposalId); let proposalEntity = new AddresslistVotingProposal(proposalId); proposalEntity.dao = daoId; - proposalEntity.plugin = pluginAddress.toHexString(); + proposalEntity.plugin = pluginEntityId; proposalEntity.pluginProposalId = pluginProposalId; proposalEntity.creator = event.params.creator; proposalEntity.metadata = metadata; @@ -75,10 +83,7 @@ export function _handleProposalCreated( let actions = proposal.value.value4; for (let index = 0; index < actions.length; index++) { const action = actions[index]; - - let actionId = getProposalId(pluginAddress, pluginProposalId) - .concat('_') - .concat(index.toString()); + let actionId = generateActionEntityId(proposalId, index); let actionEntity = new Action(actionId); actionEntity.to = action.to; @@ -110,12 +115,13 @@ export function _handleProposalCreated( export function handleVoteCast(event: VoteCast): void { const pluginProposalId = event.params.proposalId; - const member = event.params.voter.toHexString(); + const memberAddress = event.params.voter; const pluginAddress = event.address; - const pluginId = pluginAddress.toHexString(); - const memberId = pluginId.concat('_').concat(member); - let proposalId = getProposalId(pluginAddress, pluginProposalId); - let voterVoteId = member.concat('_').concat(proposalId); + const pluginEntityId = generatePluginEntityId(pluginAddress); + const memberEntityId = generateMemberEntityId(pluginAddress, memberAddress); + + let proposalId = generateProposalEntityId(pluginAddress, pluginProposalId); + let voterVoteId = generateVoteEntityId(memberAddress, proposalId); let voteOption = VOTER_OPTIONS.get(event.params.voteOption); if (voteOption === 'None') { @@ -128,7 +134,7 @@ export function handleVoteCast(event: VoteCast): void { voterProposalVoteEntity.updatedAt = event.block.timestamp; } else { voterProposalVoteEntity = new AddresslistVotingVote(voterVoteId); - voterProposalVoteEntity.voter = memberId; + voterProposalVoteEntity.voter = memberEntityId; voterProposalVoteEntity.proposal = proposalId; voterProposalVoteEntity.createdAt = event.block.timestamp; voterProposalVoteEntity.voteReplaced = false; @@ -201,7 +207,7 @@ export function handleVoteCast(event: VoteCast): void { export function handleProposalExecuted(event: ProposalExecuted): void { let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); + let proposalId = generateProposalEntityId(event.address, pluginProposalId); let proposalEntity = AddresslistVotingProposal.load(proposalId); if (proposalEntity) { @@ -217,7 +223,9 @@ export function handleProposalExecuted(event: ProposalExecuted): void { export function handleVotingSettingsUpdated( event: VotingSettingsUpdated ): void { - let packageEntity = AddresslistVotingPlugin.load(event.address.toHexString()); + let pluginAddress = event.address; + let pluginEntityId = generatePluginEntityId(pluginAddress); + let packageEntity = AddresslistVotingPlugin.load(pluginEntityId); if (packageEntity) { packageEntity.votingMode = VOTING_MODES.get(event.params.votingMode); packageEntity.supportThreshold = event.params.supportThreshold; @@ -231,15 +239,15 @@ export function handleVotingSettingsUpdated( export function handleMembersAdded(event: MembersAdded): void { let members = event.params.members; for (let index = 0; index < members.length; index++) { - const member = members[index].toHexString(); - const pluginId = event.address.toHexString(); - const memberId = pluginId + '_' + member; - - let voterEntity = AddresslistVotingVoter.load(memberId); + const memberAddress = members[index]; + const pluginAddress = event.address; + const pluginEntityId = generatePluginEntityId(pluginAddress); + const memberEntityId = generateMemberEntityId(pluginAddress, memberAddress); + let voterEntity = AddresslistVotingVoter.load(memberEntityId); if (!voterEntity) { - voterEntity = new AddresslistVotingVoter(memberId); - voterEntity.address = member; - voterEntity.plugin = pluginId; + voterEntity = new AddresslistVotingVoter(memberEntityId); + voterEntity.address = generateEntityIdFromAddress(memberAddress); + voterEntity.plugin = pluginEntityId; voterEntity.save(); } } @@ -248,13 +256,13 @@ export function handleMembersAdded(event: MembersAdded): void { export function handleMembersRemoved(event: MembersRemoved): void { let members = event.params.members; for (let index = 0; index < members.length; index++) { - const member = members[index].toHexString(); - const pluginId = event.address.toHexString(); - const memberId = pluginId + '_' + member; + const memberAddress = members[index]; + let pluginAddress = event.address; + const memberEntityId = generateMemberEntityId(pluginAddress, memberAddress); - let voterEntity = AddresslistVotingVoter.load(memberId); + let voterEntity = AddresslistVotingVoter.load(memberEntityId); if (voterEntity) { - store.remove('AddresslistVotingVoter', memberId); + store.remove('AddresslistVotingVoter', memberEntityId); } } } diff --git a/packages/subgraph/src/packages/admin/admin.ts b/packages/subgraph/src/packages/admin/admin.ts index a68d0b2f6..411a4e9d7 100644 --- a/packages/subgraph/src/packages/admin/admin.ts +++ b/packages/subgraph/src/packages/admin/admin.ts @@ -10,7 +10,12 @@ import { ProposalCreated, ProposalExecuted, } from '../../../generated/templates/Admin/Admin'; -import {getProposalId} from '../../utils/proposals'; +import {generateAdministratorAdminPluginEntityId} from '../../utils/ids'; +import { + generateActionEntityId, + generatePluginEntityId, + generateProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {dataSource, DataSourceContext} from '@graphprotocol/graph-ts'; export function handleProposalCreated(event: ProposalCreated): void { @@ -27,13 +32,17 @@ export function _handleProposalCreated( metadata: string ): void { let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); - let pluginId = event.address.toHexString(); + let pluginAddress = event.address; + let pluginEntityId = generatePluginEntityId(pluginAddress); + let proposalEntityId = generateProposalEntityId( + pluginAddress, + pluginProposalId + ); let administratorAddress = event.params.creator; - let proposalEntity = new AdminProposal(proposalId); + let proposalEntity = new AdminProposal(proposalEntityId); proposalEntity.dao = daoId; - proposalEntity.plugin = pluginId; + proposalEntity.plugin = pluginEntityId; proposalEntity.pluginProposalId = pluginProposalId; proposalEntity.creator = administratorAddress; proposalEntity.metadata = metadata; @@ -43,17 +52,15 @@ export function _handleProposalCreated( proposalEntity.endDate = event.params.endDate; proposalEntity.administrator = administratorAddress.toHexString(); proposalEntity.allowFailureMap = event.params.allowFailureMap; - - // Administrator - let administratorId = administratorAddress - .toHexString() - .concat('_') - .concat(pluginId); - let adminMemberEntity = AdministratorAdminPlugin.load(administratorId); + let administratorEntityId = generateAdministratorAdminPluginEntityId( + administratorAddress, + pluginAddress + ); + let adminMemberEntity = AdministratorAdminPlugin.load(administratorEntityId); if (!adminMemberEntity) { - adminMemberEntity = new AdministratorAdminPlugin(administratorId); + adminMemberEntity = new AdministratorAdminPlugin(administratorEntityId); adminMemberEntity.administrator = administratorAddress.toHexString(); - adminMemberEntity.plugin = pluginId; + adminMemberEntity.plugin = pluginEntityId; adminMemberEntity.save(); } let administratorEntity = Administrator.load( @@ -70,16 +77,13 @@ export function _handleProposalCreated( for (let index = 0; index < actions.length; index++) { const action = actions[index]; - let actionId = getProposalId(event.address, pluginProposalId) - .concat('_') - .concat(index.toString()); - - let actionEntity = new Action(actionId); + let actionEntityId = generateActionEntityId(proposalEntityId, index); + let actionEntity = new Action(actionEntityId); actionEntity.to = action.to; actionEntity.value = action.value; actionEntity.data = action.data; actionEntity.dao = daoId; - actionEntity.proposal = proposalId; + actionEntity.proposal = proposalEntityId; actionEntity.save(); } @@ -88,9 +92,12 @@ export function _handleProposalCreated( export function handleProposalExecuted(event: ProposalExecuted): void { let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); + let proposalEntityId = generateProposalEntityId( + event.address, + pluginProposalId + ); - let proposalEntity = AdminProposal.load(proposalId); + let proposalEntity = AdminProposal.load(proposalEntityId); if (proposalEntity) { proposalEntity.executed = true; proposalEntity.executionTxHash = event.transaction.hash; diff --git a/packages/subgraph/src/packages/admin/adminMembers.ts b/packages/subgraph/src/packages/admin/adminMembers.ts index aaa16a529..fd7f46ee1 100644 --- a/packages/subgraph/src/packages/admin/adminMembers.ts +++ b/packages/subgraph/src/packages/admin/adminMembers.ts @@ -3,6 +3,11 @@ import { AdministratorAdminPlugin, } from '../../../generated/schema'; import {Granted, Revoked} from '../../../generated/templates/Admin/DAO'; +import {generateAdministratorAdminPluginEntityId} from '../../utils/ids'; +import { + generateEntityIdFromAddress, + generatePluginEntityId, +} from '@aragon/osx-commons-subgraph'; import {dataSource, store} from '@graphprotocol/graph-ts'; export function handleGranted(event: Granted): void { @@ -12,16 +17,22 @@ export function handleGranted(event: Granted): void { event.params.where.toHexString() ) ) { - let pluginAddress = event.params.where.toHexString(); - let administratorAddress = event.params.who.toHexString(); - let administrator = Administrator.load(administratorAddress); + let pluginAddress = event.params.where; + let administratorAddress = event.params.who; + let pluginEntityId = generatePluginEntityId(pluginAddress); + let administratorEntityId = + generateEntityIdFromAddress(administratorAddress); + let administrator = Administrator.load(administratorEntityId); if (!administrator) { - administrator = new Administrator(administratorAddress); - administrator.address = administratorAddress; + administrator = new Administrator(administratorEntityId); + administrator.address = administratorEntityId; administrator.save(); } - let administratorMappingId = `${pluginAddress}_${administratorAddress}`; + let administratorMappingId = generateAdministratorAdminPluginEntityId( + pluginAddress, + administratorAddress + ); let administratorPluginMapping = AdministratorAdminPlugin.load( administratorMappingId ); @@ -29,8 +40,8 @@ export function handleGranted(event: Granted): void { administratorPluginMapping = new AdministratorAdminPlugin( administratorMappingId ); - administratorPluginMapping.administrator = administratorAddress; - administratorPluginMapping.plugin = pluginAddress; + administratorPluginMapping.administrator = administratorEntityId; + administratorPluginMapping.plugin = pluginEntityId; administratorPluginMapping.save(); } } @@ -43,7 +54,12 @@ export function handleRevoked(event: Revoked): void { event.params.where.toHexString() ) ) { - let mappingId = `${event.params.where.toHexString()}_${event.params.who.toHexString()}`; + // where is the plugin address + // who is the administrator address + let mappingId = generateAdministratorAdminPluginEntityId( + event.params.where, + event.params.who + ); if (AdministratorAdminPlugin.load(mappingId)) { store.remove('AdministratorAdminPlugin', mappingId); } diff --git a/packages/subgraph/src/packages/multisig/multisig.ts b/packages/subgraph/src/packages/multisig/multisig.ts index b8017af4d..a2f9a6a97 100644 --- a/packages/subgraph/src/packages/multisig/multisig.ts +++ b/packages/subgraph/src/packages/multisig/multisig.ts @@ -14,7 +14,13 @@ import { Approved, MultisigSettingsUpdated, } from '../../../generated/templates/Multisig/Multisig'; +import {generateMemberEntityId, generateVoterEntityId} from '../../utils/ids'; import {getProposalId} from '../../utils/proposals'; +import { + generateActionEntityId, + generatePluginEntityId, + generateProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {dataSource, store} from '@graphprotocol/graph-ts'; export function handleProposalCreated(event: ProposalCreated): void { @@ -31,11 +37,16 @@ export function _handleProposalCreated( metadata: string ): void { let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); - - let proposalEntity = new MultisigProposal(proposalId); + let pluginAddress = event.address; + let proposalEntityId = generateProposalEntityId( + pluginAddress, + pluginProposalId + ); + let pluginEntityId = generatePluginEntityId(pluginAddress); + + let proposalEntity = new MultisigProposal(proposalEntityId); proposalEntity.dao = daoId; - proposalEntity.plugin = event.address.toHexString(); + proposalEntity.plugin = pluginEntityId; proposalEntity.pluginProposalId = pluginProposalId; proposalEntity.creator = event.params.creator; proposalEntity.metadata = metadata; @@ -45,7 +56,7 @@ export function _handleProposalCreated( proposalEntity.endDate = event.params.endDate; proposalEntity.allowFailureMap = event.params.allowFailureMap; - let contract = Multisig.bind(event.address); + let contract = Multisig.bind(pluginAddress); let proposal = contract.try_getProposal(pluginProposalId); if (!proposal.reverted) { @@ -63,16 +74,14 @@ export function _handleProposalCreated( for (let index = 0; index < actions.length; index++) { const action = actions[index]; - let actionId = getProposalId(event.address, pluginProposalId) - .concat('_') - .concat(index.toString()); + let actionId = generateActionEntityId(proposalEntityId, index); let actionEntity = new Action(actionId); actionEntity.to = action.to; actionEntity.value = action.value; actionEntity.data = action.data; actionEntity.dao = daoId; - actionEntity.proposal = proposalId; + actionEntity.proposal = proposalEntityId; actionEntity.save(); } proposalEntity.isSignaling = actions.length == 0; @@ -81,7 +90,7 @@ export function _handleProposalCreated( proposalEntity.save(); // update vote length - let packageEntity = MultisigPlugin.load(event.address.toHexString()); + let packageEntity = MultisigPlugin.load(pluginEntityId); if (packageEntity) { let voteLength = contract.try_proposalCount(); if (!voteLength.reverted) { @@ -92,27 +101,33 @@ export function _handleProposalCreated( } export function handleApproved(event: Approved): void { - const member = event.params.approver.toHexString(); - const pluginId = event.address.toHexString(); - const memberId = pluginId.concat('_').concat(member); + let memberAddress = event.params.approver; + let pluginAddress = event.address; + let memberEntityId = generateMemberEntityId(pluginAddress, memberAddress); let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); - let approverProposalId = member.concat('_').concat(proposalId); + let proposalEntityId = generateProposalEntityId( + event.address, + pluginProposalId + ); + let approverProposalId = generateVoterEntityId( + memberEntityId, + proposalEntityId + ); let approverProposalEntity = MultisigProposalApprover.load(approverProposalId); if (!approverProposalEntity) { approverProposalEntity = new MultisigProposalApprover(approverProposalId); - approverProposalEntity.approver = memberId; - approverProposalEntity.proposal = proposalId; + approverProposalEntity.approver = memberEntityId; + approverProposalEntity.proposal = proposalEntityId; } approverProposalEntity.createdAt = event.block.timestamp; approverProposalEntity.save(); // update count - let proposalEntity = MultisigProposal.load(proposalId); + let proposalEntity = MultisigProposal.load(proposalEntityId); if (proposalEntity) { - let contract = Multisig.bind(event.address); + let contract = Multisig.bind(pluginAddress); let proposal = contract.try_getProposal(pluginProposalId); if (!proposal.reverted) { @@ -136,9 +151,12 @@ export function handleApproved(event: Approved): void { export function handleProposalExecuted(event: ProposalExecuted): void { let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); + let proposalEntityId = generateProposalEntityId( + event.address, + pluginProposalId + ); - let proposalEntity = MultisigProposal.load(proposalId); + let proposalEntity = MultisigProposal.load(proposalEntityId); if (proposalEntity) { proposalEntity.approvalReached = false; proposalEntity.executed = true; @@ -152,15 +170,17 @@ export function handleProposalExecuted(event: ProposalExecuted): void { export function handleMembersAdded(event: MembersAdded): void { const members = event.params.members; for (let index = 0; index < members.length; index++) { - const member = members[index].toHexString(); - const pluginId = event.address.toHexString(); - const memberId = pluginId + '_' + member; + const memberAddress = members[index]; + const pluginEntityId = generatePluginEntityId(event.address); + const memberEntityId = [pluginEntityId, memberAddress.toHexString()].join( + '_' + ); - let approverEntity = MultisigApprover.load(memberId); + let approverEntity = MultisigApprover.load(memberEntityId); if (!approverEntity) { - approverEntity = new MultisigApprover(memberId); - approverEntity.address = member; - approverEntity.plugin = pluginId; + approverEntity = new MultisigApprover(memberEntityId); + approverEntity.address = memberAddress.toHexString(); + approverEntity.plugin = pluginEntityId; approverEntity.save(); } } @@ -169,13 +189,15 @@ export function handleMembersAdded(event: MembersAdded): void { export function handleMembersRemoved(event: MembersRemoved): void { const members = event.params.members; for (let index = 0; index < members.length; index++) { - const member = members[index].toHexString(); - const pluginId = event.address.toHexString(); - const memberId = pluginId + '_' + member; + const memberAddress = members[index]; + const pluginEntityId = generatePluginEntityId(event.address); + const memberEntityId = [pluginEntityId, memberAddress.toHexString()].join( + '_' + ); - const approverEntity = MultisigApprover.load(memberId); + const approverEntity = MultisigApprover.load(memberEntityId); if (approverEntity) { - store.remove('MultisigApprover', memberId); + store.remove('MultisigApprover', memberEntityId); } } } @@ -183,7 +205,9 @@ export function handleMembersRemoved(event: MembersRemoved): void { export function handleMultisigSettingsUpdated( event: MultisigSettingsUpdated ): void { - let packageEntity = MultisigPlugin.load(event.address.toHexString()); + let packageEntity = MultisigPlugin.load( + generatePluginEntityId(event.address) + ); if (packageEntity) { packageEntity.onlyListed = event.params.onlyListed; packageEntity.minApprovals = event.params.minApprovals; diff --git a/packages/subgraph/src/packages/token/governance-erc20.ts b/packages/subgraph/src/packages/token/governance-erc20.ts index 48fa707e5..c4f032c6b 100644 --- a/packages/subgraph/src/packages/token/governance-erc20.ts +++ b/packages/subgraph/src/packages/token/governance-erc20.ts @@ -5,13 +5,17 @@ import { DelegateVotesChanged, } from '../../../generated/templates/GovernanceERC20/GovernanceERC20'; import {Transfer} from '../../../generated/templates/TokenVoting/ERC20'; +import {generateMemberEntityId} from '../../utils/ids'; import {Address, BigInt, dataSource, store} from '@graphprotocol/graph-ts'; function getOrCreateMember(user: Address, pluginId: string): TokenVotingMember { - let id = [user.toHexString(), pluginId].join('_'); - let member = TokenVotingMember.load(id); + let memberEntityId = generateMemberEntityId( + user, + Address.fromString(pluginId) + ); + let member = TokenVotingMember.load(memberEntityId); if (!member) { - member = new TokenVotingMember(id); + member = new TokenVotingMember(memberEntityId); member.address = user; member.balance = BigInt.zero(); member.plugin = pluginId; diff --git a/packages/subgraph/src/packages/token/token-voting.ts b/packages/subgraph/src/packages/token/token-voting.ts index cc5aeb650..ee538f88a 100644 --- a/packages/subgraph/src/packages/token/token-voting.ts +++ b/packages/subgraph/src/packages/token/token-voting.ts @@ -15,8 +15,14 @@ import { TokenVoting, } from '../../../generated/templates/TokenVoting/TokenVoting'; import {RATIO_BASE, VOTER_OPTIONS, VOTING_MODES} from '../../utils/constants'; -import {getProposalId} from '../../utils/proposals'; +import {generateMemberEntityId, generateVoteEntityId} from '../../utils/ids'; import {identifyAndFetchOrCreateERC20TokenEntity} from '../../utils/tokens/erc20'; +import { + generateActionEntityId, + generatePluginEntityId, + generateProposalEntityId, + generateEntityIdFromAddress, +} from '@aragon/osx-commons-subgraph'; import {BigInt, dataSource, DataSourceContext} from '@graphprotocol/graph-ts'; export function handleProposalCreated(event: ProposalCreated): void { @@ -33,12 +39,16 @@ export function _handleProposalCreated( metadata: string ): void { let pluginAddress = event.address; + let pluginEntityId = generatePluginEntityId(pluginAddress); let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(pluginAddress, pluginProposalId); + let proposalEntityId = generateProposalEntityId( + pluginAddress, + pluginProposalId + ); - let proposalEntity = new TokenVotingProposal(proposalId); + let proposalEntity = new TokenVotingProposal(proposalEntityId); proposalEntity.dao = daoId; - proposalEntity.plugin = pluginAddress.toHexString(); + proposalEntity.plugin = pluginEntityId; proposalEntity.pluginProposalId = pluginProposalId; proposalEntity.creator = event.params.creator; proposalEntity.metadata = metadata; @@ -47,7 +57,7 @@ export function _handleProposalCreated( proposalEntity.allowFailureMap = event.params.allowFailureMap; proposalEntity.approvalReached = false; - let contract = TokenVoting.bind(event.address); + let contract = TokenVoting.bind(pluginAddress); let proposal = contract.try_getProposal(pluginProposalId); if (!proposal.reverted) { @@ -77,16 +87,14 @@ export function _handleProposalCreated( for (let index = 0; index < actions.length; index++) { const action = actions[index]; - let actionId = getProposalId(event.address, pluginProposalId) - .concat('_') - .concat(index.toString()); + let actionId = generateActionEntityId(proposalEntityId, index); let actionEntity = new Action(actionId); actionEntity.to = action.to; actionEntity.value = action.value; actionEntity.data = action.data; actionEntity.dao = daoId; - actionEntity.proposal = proposalId; + actionEntity.proposal = proposalEntityId; actionEntity.save(); } proposalEntity.isSignaling = actions.length == 0; @@ -100,7 +108,7 @@ export function _handleProposalCreated( proposalEntity.save(); // update vote length - let packageEntity = TokenVotingPlugin.load(event.address.toHexString()); + let packageEntity = TokenVotingPlugin.load(pluginEntityId); if (packageEntity) { let voteLength = contract.try_proposalCount(); if (!voteLength.reverted) { @@ -111,26 +119,30 @@ export function _handleProposalCreated( } export function handleVoteCast(event: VoteCast): void { - let pluginId = event.address.toHexString(); - let voter = event.params.voter.toHexString(); - let voterId = pluginId.concat('_').concat(voter); + let pluginAddress = event.address; + let voterAddress = event.params.voter; + let voterEntityId = generateMemberEntityId(pluginAddress, voterAddress); let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); - let voterVoteId = voter.concat('_').concat(proposalId); + let proposalEntityId = generateProposalEntityId( + pluginAddress, + pluginProposalId + ); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let voterVoteEntityId = generateVoteEntityId(voterAddress, proposalEntityId); let voteOption = VOTER_OPTIONS.get(event.params.voteOption); if (voteOption === 'None') { return; } - let voterProposalVoteEntity = TokenVotingVote.load(voterVoteId); + let voterProposalVoteEntity = TokenVotingVote.load(voterVoteEntityId); if (voterProposalVoteEntity) { voterProposalVoteEntity.voteReplaced = true; voterProposalVoteEntity.updatedAt = event.block.timestamp; } else { - voterProposalVoteEntity = new TokenVotingVote(voterVoteId); - voterProposalVoteEntity.voter = voterId; - voterProposalVoteEntity.proposal = proposalId; + voterProposalVoteEntity = new TokenVotingVote(voterVoteEntityId); + voterProposalVoteEntity.voter = voterEntityId; + voterProposalVoteEntity.proposal = proposalEntityId; voterProposalVoteEntity.createdAt = event.block.timestamp; voterProposalVoteEntity.voteReplaced = false; voterProposalVoteEntity.updatedAt = BigInt.zero(); @@ -140,11 +152,11 @@ export function handleVoteCast(event: VoteCast): void { voterProposalVoteEntity.save(); // voter - let voterEntity = TokenVotingVoter.load(voterId); + let voterEntity = TokenVotingVoter.load(voterEntityId); if (!voterEntity) { - voterEntity = new TokenVotingVoter(voterId); - voterEntity.address = voter; - voterEntity.plugin = pluginId; + voterEntity = new TokenVotingVoter(voterEntityId); + voterEntity.address = voterEntityId; + voterEntity.plugin = pluginEntityId; voterEntity.lastUpdated = event.block.timestamp; voterEntity.save(); } else { @@ -153,9 +165,9 @@ export function handleVoteCast(event: VoteCast): void { } // update count - let proposalEntity = TokenVotingProposal.load(proposalId); + let proposalEntity = TokenVotingProposal.load(proposalEntityId); if (proposalEntity) { - let contract = TokenVoting.bind(event.address); + let contract = TokenVoting.bind(pluginAddress); let proposal = contract.try_getProposal(pluginProposalId); if (!proposal.reverted) { @@ -215,9 +227,12 @@ export function handleVoteCast(event: VoteCast): void { export function handleProposalExecuted(event: ProposalExecuted): void { let pluginProposalId = event.params.proposalId; - let proposalId = getProposalId(event.address, pluginProposalId); + let proposalEntityId = generateProposalEntityId( + event.address, + pluginProposalId + ); - let proposalEntity = TokenVotingProposal.load(proposalId); + let proposalEntity = TokenVotingProposal.load(proposalEntityId); if (proposalEntity) { proposalEntity.executed = true; proposalEntity.approvalReached = false; @@ -231,7 +246,9 @@ export function handleProposalExecuted(event: ProposalExecuted): void { export function handleVotingSettingsUpdated( event: VotingSettingsUpdated ): void { - let packageEntity = TokenVotingPlugin.load(event.address.toHexString()); + let packageEntity = TokenVotingPlugin.load( + generatePluginEntityId(event.address) + ); if (packageEntity) { packageEntity.votingMode = VOTING_MODES.get(event.params.votingMode); packageEntity.supportThreshold = event.params.supportThreshold; @@ -246,7 +263,8 @@ export function handleMembershipContractAnnounced( event: MembershipContractAnnounced ): void { let token = event.params.definingContract; - let packageEntity = TokenVotingPlugin.load(event.address.toHexString()); + let pluginEntityId = generatePluginEntityId(event.address); + let packageEntity = TokenVotingPlugin.load(pluginEntityId); if (packageEntity) { let tokenAddress = identifyAndFetchOrCreateERC20TokenEntity(token); @@ -260,7 +278,7 @@ export function handleMembershipContractAnnounced( // Both GovernanceWrappedERC20/GovernanceERC20 use the `Transfer` event, so // It's safe to create the same type of template for them. let context = new DataSourceContext(); - context.setString('pluginId', event.address.toHexString()); + context.setString('pluginId', pluginEntityId); GovernanceERC20.createWithContext(event.params.definingContract, context); } } diff --git a/packages/subgraph/src/plugin/pluginRepo.ts b/packages/subgraph/src/plugin/pluginRepo.ts index 5591c8636..756b2d745 100644 --- a/packages/subgraph/src/plugin/pluginRepo.ts +++ b/packages/subgraph/src/plugin/pluginRepo.ts @@ -11,11 +11,18 @@ import { Revoked, } from '../../generated/templates/PluginRepoTemplate/PluginRepo'; import {getPluginVersionId} from './utils'; +import { + generatePermissionEntityId, + generatePluginReleaseEntityId, + generatePluginRepoEntityId, + generatePluginSetupEntityId, + generatePluginVersionEntityId, +} from '@aragon/osx-commons-subgraph'; import {store} from '@graphprotocol/graph-ts'; export function handleVersionCreated(event: VersionCreated): void { // PluginSetup - let pluginSetupId = event.params.pluginSetup.toHexString(); + let pluginSetupId = generatePluginSetupEntityId(event.params.pluginSetup); let pluginSetupEntity = PluginSetup.load(pluginSetupId); if (!pluginSetupEntity) { @@ -24,23 +31,25 @@ export function handleVersionCreated(event: VersionCreated): void { } // PluginVersion - let pluginRepoId = event.address.toHexString(); - let pluginReleaseId = pluginRepoId - .concat('_') - .concat(event.params.release.toString()); - - let pluginVersionId = getPluginVersionId( - pluginRepoId, - event.params.release, - event.params.build + const pluginRepoAddress = event.address; + const build = event.params.build; + const release = event.params.release; + let pluginReleaseId = generatePluginReleaseEntityId( + pluginRepoAddress, + release + ); + let pluginVersionId = generatePluginVersionEntityId( + pluginRepoAddress, + release, + build ); let entity = new PluginVersion(pluginVersionId); - entity.pluginRepo = event.address.toHexString(); + entity.pluginRepo = pluginRepoAddress.toHexString(); entity.pluginSetup = pluginSetupId; entity.release = pluginReleaseId; - entity.build = event.params.build; + entity.build = build; entity.metadata = event.params.buildMetadata.toString(); entity.save(); @@ -49,13 +58,15 @@ export function handleVersionCreated(event: VersionCreated): void { export function handleReleaseMetadataUpdated( event: ReleaseMetadataUpdated ): void { - let pluginRepoId = event.address.toHexString(); + let pluginRepoAddress = event.address; + let pluginRepoId = generatePluginRepoEntityId(pluginRepoAddress); let pluginRelease = event.params.release; let releaseMetadata = event.params.releaseMetadata.toString(); - let pluginReleaseEntityId = pluginRepoId - .concat('_') - .concat(pluginRelease.toString()); + let pluginReleaseEntityId = generatePluginReleaseEntityId( + pluginRepoAddress, + pluginRelease + ); let pluginReleaseEntity = PluginRelease.load(pluginReleaseEntityId); if (!pluginReleaseEntity) { @@ -69,19 +80,17 @@ export function handleReleaseMetadataUpdated( } export function handleGranted(event: Granted): void { - const contractAddress = event.address.toHexString(); + const contractAddress = event.address; const where = event.params.where; const permissionId = event.params.permissionId; const who = event.params.who; - const permissionEntityId = [ + const permissionEntityId = generatePermissionEntityId( contractAddress, - permissionId.toHexString(), - where.toHexString(), - who.toHexString(), - ].join('_'); - - const pluginRepo = contractAddress; + permissionId, + where, + who + ); // Permission let permissionEntity = Permission.load(permissionEntityId); @@ -93,7 +102,7 @@ export function handleGranted(event: Granted): void { permissionEntity.actor = event.params.here; permissionEntity.condition = event.params.condition; - permissionEntity.pluginRepo = pluginRepo; + permissionEntity.pluginRepo = contractAddress.toHexString(); permissionEntity.save(); } @@ -101,17 +110,17 @@ export function handleGranted(event: Granted): void { export function handleRevoked(event: Revoked): void { // permission - const contractAddress = event.address.toHexString(); + const contractAddress = event.address; const where = event.params.where; const permissionId = event.params.permissionId; const who = event.params.who; - const permissionEntityId = [ + const permissionEntityId = generatePermissionEntityId( contractAddress, - permissionId.toHexString(), - where.toHexString(), - who.toHexString(), - ].join('_'); + permissionId, + where, + who + ); const permissionEntity = Permission.load(permissionEntityId); if (permissionEntity) { diff --git a/packages/subgraph/src/plugin/pluginSetupProcessor.ts b/packages/subgraph/src/plugin/pluginSetupProcessor.ts index ae58e873b..f6eb236bb 100644 --- a/packages/subgraph/src/plugin/pluginSetupProcessor.ts +++ b/packages/subgraph/src/plugin/pluginSetupProcessor.ts @@ -11,32 +11,46 @@ import { PluginPermission, PluginPreparation, } from '../../generated/schema'; +import {addPlugin, PERMISSION_OPERATIONS} from './utils'; import { - addPlugin, - getPluginInstallationId, - getPluginVersionId, - PERMISSION_OPERATIONS, -} from './utils'; + generateDaoEntityId, + generatePluginEntityId, + generatePluginInstallationEntityId, + generatePluginPermissionEntityId, + generatePluginPreparationEntityId, + generatePluginRepoEntityId, + generatePluginVersionEntityId, +} from '@aragon/osx-commons-subgraph'; import {Bytes, log} from '@graphprotocol/graph-ts'; export function handleInstallationPrepared(event: InstallationPrepared): void { - let dao = event.params.dao.toHexString(); - let plugin = event.params.plugin.toHexString(); - let setupId = event.params.preparedSetupId.toHexString(); - let pluginRepo = event.params.pluginSetupRepo.toHexString(); - let pluginVersionId = getPluginVersionId( - pluginRepo, + let daoAddress = event.params.dao; + let pluginAddress = event.params.plugin; + let pluginRepoAddress = event.params.pluginSetupRepo; + let daoEntityId = generateDaoEntityId(daoAddress); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let pluginRepoEntityId = generatePluginRepoEntityId(pluginRepoAddress); + let preparedSetupId = event.params.preparedSetupId; + + let pluginVersionId = generatePluginVersionEntityId( + pluginRepoAddress, event.params.versionTag.release, event.params.versionTag.build ); - let installationId = getPluginInstallationId(dao, plugin); + let installationId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); if (!installationId) { - log.error('Failed to get installationId', [dao, plugin]); + log.error('Failed to get installationId', [daoEntityId, pluginEntityId]); return; } - - let preparationId = `${installationId.toHexString()}_${setupId}`; + installationId = installationId as string; + let preparationId = generatePluginPreparationEntityId( + installationId, + preparedSetupId + ); let helpers: Bytes[] = []; for (let i = 0; i < event.params.preparedSetupData.helpers.length; i++) { @@ -44,11 +58,11 @@ export function handleInstallationPrepared(event: InstallationPrepared): void { } let preparationEntity = new PluginPreparation(preparationId); - preparationEntity.installation = installationId.toHexString(); + preparationEntity.installation = installationId; preparationEntity.creator = event.params.sender; - preparationEntity.dao = dao; + preparationEntity.dao = daoEntityId; preparationEntity.preparedSetupId = event.params.preparedSetupId; - preparationEntity.pluginRepo = event.params.pluginSetupRepo.toHexString(); + preparationEntity.pluginRepo = pluginRepoEntityId; preparationEntity.pluginVersion = pluginVersionId; preparationEntity.data = event.params.data; preparationEntity.pluginAddress = event.params.plugin; @@ -58,8 +72,14 @@ export function handleInstallationPrepared(event: InstallationPrepared): void { for (let i = 0; i < event.params.preparedSetupData.permissions.length; i++) { let permission = event.params.preparedSetupData.permissions[i]; + let permissionId = generatePluginPermissionEntityId( + preparationId, + permission.operation, + permission.where, + permission.who, + permission.permissionId + ); let operation = PERMISSION_OPERATIONS.get(permission.operation); - let permissionId = `${preparationId}_${operation}_${permission.where.toHexString()}_${permission.who.toHexString()}_${permission.permissionId.toHexString()}`; let permissionEntity = new PluginPermission(permissionId); permissionEntity.pluginPreparation = preparationId; permissionEntity.operation = operation; @@ -72,31 +92,41 @@ export function handleInstallationPrepared(event: InstallationPrepared): void { permissionEntity.save(); } - let pluginEntity = PluginInstallation.load(installationId.toHexString()); + let pluginEntity = PluginInstallation.load(installationId); if (!pluginEntity) { - pluginEntity = new PluginInstallation(installationId.toHexString()); + pluginEntity = new PluginInstallation(installationId); } pluginEntity.state = 'InstallationPrepared'; - pluginEntity.dao = dao; + pluginEntity.dao = daoEntityId; pluginEntity.save(); - addPlugin(dao, event.params.plugin); + addPlugin(daoEntityId, event.params.plugin); } export function handleInstallationApplied(event: InstallationApplied): void { - let dao = event.params.dao.toHexString(); - let plugin = event.params.plugin.toHexString(); - let installationId = getPluginInstallationId(dao, plugin); + let daoAddress = event.params.dao; + let pluginAddress = event.params.plugin; + let daoEntityId = generateDaoEntityId(daoAddress); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let installationId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); if (!installationId) { - log.error('Failed to get installationId', [dao, plugin]); + log.error('Failed to get installationId', [daoEntityId, pluginEntityId]); return; } - let preparationId = `${installationId.toHexString()}_${event.params.preparedSetupId.toHexString()}`; - let pluginEntity = PluginInstallation.load(installationId.toHexString()); + installationId = installationId as string; + let preparationId = generatePluginPreparationEntityId( + installationId, + event.params.preparedSetupId + ); + + let pluginEntity = PluginInstallation.load(installationId); if (!pluginEntity) { - pluginEntity = new PluginInstallation(installationId.toHexString()); - pluginEntity.dao = dao; + pluginEntity = new PluginInstallation(installationId); + pluginEntity.dao = daoEntityId; } let pluginPreparationEntity = PluginPreparation.load(preparationId); @@ -104,7 +134,7 @@ export function handleInstallationApplied(event: InstallationApplied): void { pluginEntity.appliedPluginRepo = pluginPreparationEntity.pluginRepo; pluginEntity.appliedVersion = pluginPreparationEntity.pluginVersion; } - pluginEntity.plugin = plugin; + pluginEntity.plugin = pluginEntityId; pluginEntity.appliedPreparation = preparationId; pluginEntity.appliedSetupId = event.params.appliedSetupId; pluginEntity.state = 'Installed'; @@ -112,24 +142,33 @@ export function handleInstallationApplied(event: InstallationApplied): void { } export function handleUpdatePrepared(event: UpdatePrepared): void { - let dao = event.params.dao.toHexString(); - let plugin = event.params.setupPayload.plugin.toHexString(); - let setupId = event.params.preparedSetupId.toHexString(); - let pluginRepo = event.params.pluginSetupRepo.toHexString(); - - let pluginVersionId = getPluginVersionId( - pluginRepo, + let daoAddress = event.params.dao; + let pluginAddress = event.params.setupPayload.plugin; + let pluginRepoAddress = event.params.pluginSetupRepo; + let setupId = event.params.preparedSetupId; + let daoEntityId = generateDaoEntityId(daoAddress); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let pluginVersionId = generatePluginVersionEntityId( + pluginRepoAddress, event.params.versionTag.release, event.params.versionTag.build ); - let installationId = getPluginInstallationId(dao, plugin); + let installationId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); if (!installationId) { - log.error('Failed to get installationId', [dao, plugin]); + log.error('Failed to get installationId', [daoEntityId, pluginEntityId]); return; } - let preparationId = `${installationId.toHexString()}_${setupId}`; + installationId = installationId as string; + + let preparationId = generatePluginPreparationEntityId( + installationId, + setupId + ); let helpers: Bytes[] = []; for (let i = 0; i < event.params.preparedSetupData.helpers.length; i++) { @@ -137,11 +176,13 @@ export function handleUpdatePrepared(event: UpdatePrepared): void { } let preparationEntity = new PluginPreparation(preparationId); - preparationEntity.installation = installationId.toHexString(); + preparationEntity.installation = installationId; preparationEntity.creator = event.params.sender; - preparationEntity.dao = dao; + preparationEntity.dao = daoEntityId; preparationEntity.preparedSetupId = event.params.preparedSetupId; - preparationEntity.pluginRepo = event.params.pluginSetupRepo.toHexString(); + preparationEntity.pluginRepo = generatePluginEntityId( + event.params.pluginSetupRepo + ); preparationEntity.pluginVersion = pluginVersionId; preparationEntity.data = event.params.initData; preparationEntity.pluginAddress = event.params.setupPayload.plugin; @@ -152,7 +193,13 @@ export function handleUpdatePrepared(event: UpdatePrepared): void { for (let i = 0; i < event.params.preparedSetupData.permissions.length; i++) { let permission = event.params.preparedSetupData.permissions[i]; let operation = PERMISSION_OPERATIONS.get(permission.operation); - let permissionId = `${preparationId}_${operation}_${permission.where.toHexString()}_${permission.who.toHexString()}_${permission.permissionId.toHexString()}`; + let permissionId = generatePluginPermissionEntityId( + preparationId, + permission.operation, + permission.where, + permission.who, + permission.permissionId + ); let permissionEntity = new PluginPermission(permissionId); permissionEntity.pluginPreparation = preparationId; permissionEntity.operation = operation; @@ -165,10 +212,10 @@ export function handleUpdatePrepared(event: UpdatePrepared): void { permissionEntity.save(); } - let pluginEntity = PluginInstallation.load(installationId.toHexString()); + let pluginEntity = PluginInstallation.load(installationId); if (!pluginEntity) { - pluginEntity = new PluginInstallation(installationId.toHexString()); - pluginEntity.dao = dao; + pluginEntity = new PluginInstallation(installationId); + pluginEntity.dao = daoEntityId; } pluginEntity.state = 'UpdatePrepared'; @@ -176,19 +223,28 @@ export function handleUpdatePrepared(event: UpdatePrepared): void { } export function handleUpdateApplied(event: UpdateApplied): void { - let dao = event.params.dao.toHexString(); - let plugin = event.params.plugin.toHexString(); - let installationId = getPluginInstallationId(dao, plugin); + let daoAddress = event.params.dao; + let pluginAddress = event.params.plugin; + let daoEntityId = generateDaoEntityId(daoAddress); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let installationId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); if (!installationId) { - log.error('Failed to get installationId', [dao, plugin]); + log.error('Failed to get installationId', [daoEntityId, pluginEntityId]); return; } - let preparationId = `${installationId.toHexString()}_${event.params.preparedSetupId.toHexString()}`; + installationId = installationId as string; + let preparationId = generatePluginPreparationEntityId( + installationId, + event.params.preparedSetupId + ); - let pluginEntity = PluginInstallation.load(installationId.toHexString()); + let pluginEntity = PluginInstallation.load(installationId); if (!pluginEntity) { - pluginEntity = new PluginInstallation(installationId.toHexString()); - pluginEntity.dao = dao; + pluginEntity = new PluginInstallation(installationId); + pluginEntity.dao = daoEntityId; } let pluginPreparationEntity = PluginPreparation.load(preparationId); @@ -196,43 +252,53 @@ export function handleUpdateApplied(event: UpdateApplied): void { pluginEntity.appliedPluginRepo = pluginPreparationEntity.pluginRepo; pluginEntity.appliedVersion = pluginPreparationEntity.pluginVersion; } - pluginEntity.plugin = plugin; + pluginEntity.plugin = pluginEntityId; pluginEntity.appliedPreparation = preparationId; pluginEntity.appliedSetupId = event.params.appliedSetupId; pluginEntity.state = 'Installed'; pluginEntity.save(); - addPlugin(dao, event.params.plugin); + addPlugin(daoEntityId, pluginAddress); } export function handleUninstallationPrepared( event: UninstallationPrepared ): void { - let dao = event.params.dao.toHexString(); - let plugin = event.params.setupPayload.plugin.toHexString(); - let setupId = event.params.preparedSetupId.toHexString(); - let pluginRepo = event.params.pluginSetupRepo.toHexString(); - - let pluginVersionId = getPluginVersionId( - pluginRepo, + let daoAddress = event.params.dao; + let pluginAddress = event.params.setupPayload.plugin; + let setupId = event.params.preparedSetupId; + let pluginRepoAddress = event.params.pluginSetupRepo; + let daoEntityId = generateDaoEntityId(daoAddress); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let pluginRepoEntityId = generatePluginRepoEntityId(pluginRepoAddress); + + let pluginVersionId = generatePluginVersionEntityId( + pluginRepoAddress, event.params.versionTag.release, event.params.versionTag.build ); - let installationId = getPluginInstallationId(dao, plugin); + let installationId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); if (!installationId) { - log.error('Failed to get installationId', [dao, plugin]); + log.error('Failed to get installationId', [daoEntityId, pluginEntityId]); return; } + installationId = installationId as string; - let preparationId = `${installationId.toHexString()}_${setupId}`; + let preparationId = generatePluginPreparationEntityId( + installationId, + setupId + ); let preparationEntity = new PluginPreparation(preparationId); - preparationEntity.installation = installationId.toHexString(); + preparationEntity.installation = installationId; preparationEntity.creator = event.params.sender; - preparationEntity.dao = dao; + preparationEntity.dao = daoEntityId; preparationEntity.preparedSetupId = event.params.preparedSetupId; - preparationEntity.pluginRepo = event.params.pluginSetupRepo.toHexString(); + preparationEntity.pluginRepo = pluginRepoEntityId; preparationEntity.pluginVersion = pluginVersionId; preparationEntity.pluginAddress = event.params.setupPayload.plugin; preparationEntity.helpers = []; @@ -242,7 +308,13 @@ export function handleUninstallationPrepared( for (let i = 0; i < event.params.permissions.length; i++) { let permission = event.params.permissions[i]; let operation = PERMISSION_OPERATIONS.get(permission.operation); - let permissionId = `${preparationId}_${operation}_${permission.where.toHexString()}_${permission.who.toHexString()}_${permission.permissionId.toHexString()}`; + let permissionId = generatePluginPermissionEntityId( + preparationId, + permission.operation, + permission.where, + permission.who, + permission.permissionId + ); let permissionEntity = new PluginPermission(permissionId); permissionEntity.pluginPreparation = preparationId; permissionEntity.operation = operation; @@ -255,10 +327,10 @@ export function handleUninstallationPrepared( permissionEntity.save(); } - let pluginEntity = PluginInstallation.load(installationId.toHexString()); + let pluginEntity = PluginInstallation.load(installationId); if (!pluginEntity) { - pluginEntity = new PluginInstallation(installationId.toHexString()); - pluginEntity.dao = dao; + pluginEntity = new PluginInstallation(installationId); + pluginEntity.dao = daoEntityId; } pluginEntity.state = 'UninstallPrepared'; pluginEntity.save(); @@ -267,19 +339,30 @@ export function handleUninstallationPrepared( export function handleUninstallationApplied( event: UninstallationApplied ): void { - let dao = event.params.dao.toHexString(); - let plugin = event.params.plugin.toHexString(); - let installationId = getPluginInstallationId(dao, plugin); + let daoAddress = event.params.dao; + let pluginAddress = event.params.plugin; + let daoEntityId = generateDaoEntityId(daoAddress); + let pluginEntityId = generatePluginEntityId(pluginAddress); + let installationId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); if (!installationId) { - log.error('Failed to get installationId', [dao, plugin]); + log.error('Failed to get installationId', [daoEntityId, pluginEntityId]); return; } - let preparationId = `${installationId.toHexString()}_${event.params.preparedSetupId.toHexString()}`; - let pluginEntity = PluginInstallation.load(installationId.toHexString()); + installationId = installationId as string; + + let preparationId = generatePluginPreparationEntityId( + installationId, + event.params.preparedSetupId + ); + + let pluginEntity = PluginInstallation.load(installationId); if (!pluginEntity) { - pluginEntity = new PluginInstallation(installationId.toHexString()); - pluginEntity.dao = dao; + pluginEntity = new PluginInstallation(installationId); + pluginEntity.dao = daoEntityId; } pluginEntity.appliedPreparation = preparationId; pluginEntity.state = 'Uninstalled'; diff --git a/packages/subgraph/src/plugin/utils.ts b/packages/subgraph/src/plugin/utils.ts index 441006949..8fabfc118 100644 --- a/packages/subgraph/src/plugin/utils.ts +++ b/packages/subgraph/src/plugin/utils.ts @@ -26,6 +26,7 @@ import { fetchOrCreateWrappedERC20Entity, supportsERC20Wrapped, } from '../utils/tokens/erc20'; +import {generatePluginEntityId} from '@aragon/osx-commons-subgraph'; import { Address, Bytes, @@ -92,9 +93,10 @@ function createTokenVotingPlugin(plugin: Address, daoId: string): void { } function createAddresslistVotingPlugin(plugin: Address, daoId: string): void { - let packageEntity = AddresslistVotingPlugin.load(plugin.toHexString()); + let pluginEntityId = generatePluginEntityId(plugin); + let packageEntity = AddresslistVotingPlugin.load(pluginEntityId); if (!packageEntity) { - packageEntity = new AddresslistVotingPlugin(plugin.toHexString()); + packageEntity = new AddresslistVotingPlugin(pluginEntityId); packageEntity.pluginAddress = plugin; packageEntity.dao = daoId; packageEntity.proposalCount = BigInt.zero(); diff --git a/packages/subgraph/src/registries/daoRegistry.ts b/packages/subgraph/src/registries/daoRegistry.ts index ebe40c74e..c6eed91e0 100644 --- a/packages/subgraph/src/registries/daoRegistry.ts +++ b/packages/subgraph/src/registries/daoRegistry.ts @@ -1,6 +1,7 @@ import {DAORegistered} from '../../generated/DAORegistry/DAORegistry'; import {Dao} from '../../generated/schema'; import {DaoTemplateV1_0_0, DaoTemplateV1_3_0} from '../../generated/templates'; +import {generateDaoEntityId} from '@aragon/osx-commons-subgraph'; import {dataSource} from '@graphprotocol/graph-ts'; // blocklists of addresses for which we don't index the subdomain. @@ -10,10 +11,11 @@ const subdomain_blocklist_mainnet = [ ]; export function handleDAORegistered(event: DAORegistered): void { - let id = event.params.dao.toHexString(); // use dao address as id, because it should not repeat - let entity = new Dao(id); + let daoAddress = event.params.dao; // use dao address as id, because it should not repeat + let daoEntityId = generateDaoEntityId(daoAddress); + let entity = new Dao(daoEntityId); - if (!isInSubdomainBlocklist(id)) { + if (!isInSubdomainBlocklist(daoEntityId)) { entity.subdomain = event.params.subdomain; } @@ -21,8 +23,8 @@ export function handleDAORegistered(event: DAORegistered): void { entity.createdAt = event.block.timestamp; // subscribe to templates - DaoTemplateV1_0_0.create(event.params.dao); - DaoTemplateV1_3_0.create(event.params.dao); + DaoTemplateV1_0_0.create(daoAddress); + DaoTemplateV1_3_0.create(daoAddress); entity.save(); } diff --git a/packages/subgraph/src/registries/pluginRepoRegistry.ts b/packages/subgraph/src/registries/pluginRepoRegistry.ts index e316c32f8..1c9bdb73b 100644 --- a/packages/subgraph/src/registries/pluginRepoRegistry.ts +++ b/packages/subgraph/src/registries/pluginRepoRegistry.ts @@ -1,15 +1,17 @@ import {PluginRepoRegistered} from '../../generated/PluginRepoRegistry/PluginRepoRegistry'; import {PluginRepo} from '../../generated/schema'; import {PluginRepoTemplate} from '../../generated/templates'; +import {generatePluginRepoEntityId} from '@aragon/osx-commons-subgraph'; export function handlePluginRepoRegistered(event: PluginRepoRegistered): void { - let id = event.params.pluginRepo.toHexString(); - let entity = new PluginRepo(id); + let pluginRepoAddress = event.params.pluginRepo; + let pluginRepoEntityId = generatePluginRepoEntityId(pluginRepoAddress); + let entity = new PluginRepo(pluginRepoEntityId); entity.subdomain = event.params.subdomain; // subscribe to templates - PluginRepoTemplate.create(event.params.pluginRepo); + PluginRepoTemplate.create(pluginRepoAddress); entity.save(); } diff --git a/packages/subgraph/src/utils/ids.ts b/packages/subgraph/src/utils/ids.ts new file mode 100644 index 000000000..55ee89beb --- /dev/null +++ b/packages/subgraph/src/utils/ids.ts @@ -0,0 +1,57 @@ +import { + generateEntityIdFromAddress, + generateEntityIdFromBytes, +} from '@aragon/osx-commons-subgraph'; +import {Address, BigInt, Bytes} from '@graphprotocol/graph-ts'; + +export function generateTokenEntityId(tokenAddress: Address): string { + return generateEntityIdFromAddress(tokenAddress); +} + +export function generateERC1155TransferEntityId( + txHash: Bytes, + logIndex: BigInt, + actionIndex: number, + batchIndex: number +): string { + return [ + generateEntityIdFromBytes(txHash), + logIndex.toString(), + actionIndex.toString(), + batchIndex.toString(), + ].join('_'); +} + +export function generateVoterEntityId( + memberEntityId: string, + proposalId: string +): string { + return [memberEntityId, proposalId].join('_'); +} + +export function generateMemberEntityId( + pluginAddress: Address, + memberAddress: Address +): string { + return [ + generateEntityIdFromAddress(pluginAddress), + generateEntityIdFromAddress(memberAddress), + ].join('_'); +} + +export function generateVoteEntityId( + memberAddress: Address, + proposalId: string +): string { + return [generateEntityIdFromAddress(memberAddress), proposalId].join('_'); +} + +export function generateAdministratorAdminPluginEntityId( + pluginAddress: Address, + administratorAddress: Address +): string { + return [ + generateEntityIdFromAddress(pluginAddress), + generateEntityIdFromAddress(administratorAddress), + ].join('_'); +} diff --git a/packages/subgraph/src/utils/tokens/erc1155.ts b/packages/subgraph/src/utils/tokens/erc1155.ts index 76e4ca8a5..0df31fd8c 100644 --- a/packages/subgraph/src/utils/tokens/erc1155.ts +++ b/packages/subgraph/src/utils/tokens/erc1155.ts @@ -7,6 +7,7 @@ import { import {ERC1155} from '../../../generated/templates/DaoTemplateV1_0_0/ERC1155'; import {getMethodSignature} from '../bytes'; import {supportsInterface} from '../erc165'; +import {generateTokenEntityId} from '../ids'; import { DECODE_OFFSET, ERC1155_INTERFACE_ID, @@ -18,6 +19,7 @@ import { getERC1155TransferId, getTokenIdBalanceId, } from './common'; +import {generateDaoEntityId} from '@aragon/osx-commons-subgraph'; import {Address, BigInt, Bytes, ethereum} from '@graphprotocol/graph-ts'; export function supportsERC1155(token: Address): bool { @@ -340,13 +342,15 @@ function createErc1155Transfer( txHash: Bytes, timestamp: BigInt ): void { + let daoEntityId = generateDaoEntityId(dao); + let tokenEntityId = generateTokenEntityId(token); // create transfer let transfer = new ERC1155Transfer(transferId); transfer.from = from; transfer.to = to; transfer.operator = operator; - transfer.dao = dao.toHexString(); - transfer.token = token.toHexString(); + transfer.dao = daoEntityId; + transfer.token = tokenEntityId; transfer.amount = amount; transfer.tokenId = tokenId; transfer.proposal = proposalId; @@ -371,8 +375,8 @@ function createErc1155Transfer( // 2. dao calls transferFrom as an action to transfer it from `y` to itself. transfer.type = 'Deposit'; updateERC1155Balance( - dao.toHexString(), - token.toHexString(), + daoEntityId, + tokenEntityId, tokenId, amount, timestamp, @@ -382,8 +386,8 @@ function createErc1155Transfer( transfer.type = 'Withdraw'; updateERC1155Balance( - dao.toHexString(), - token.toHexString(), + daoEntityId, + tokenEntityId, tokenId, amount, timestamp, diff --git a/packages/subgraph/src/utils/tokens/erc20.ts b/packages/subgraph/src/utils/tokens/erc20.ts index e7475b7e3..025668062 100644 --- a/packages/subgraph/src/utils/tokens/erc20.ts +++ b/packages/subgraph/src/utils/tokens/erc20.ts @@ -8,7 +8,13 @@ import {ERC20} from '../../../generated/templates/DaoTemplateV1_0_0/ERC20'; import {GovernanceWrappedERC20} from '../../../generated/templates/TokenVoting/GovernanceWrappedERC20'; import {GOVERNANCE_WRAPPED_ERC20_INTERFACE_ID} from '../../utils/constants'; import {supportsInterface} from '../erc165'; +import {generateTokenEntityId} from '../ids'; import {ERC20_transfer, ERC20_transferFrom, getTransferId} from './common'; +import { + generateBalanceEntityId, + generateDaoEntityId, + generateTransferEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt, Bytes, ethereum} from '@graphprotocol/graph-ts'; export function supportsERC20Wrapped(token: Address): bool { @@ -32,14 +38,15 @@ export function supportsERC20Wrapped(token: Address): bool { export function fetchOrCreateWrappedERC20Entity( address: Address ): ERC20WrapperContract | null { + const tokenEntityId = generateTokenEntityId(address); let wrappedErc20 = GovernanceWrappedERC20.bind(address); // try load entry - let contract = ERC20WrapperContract.load(address.toHexString()); + let contract = ERC20WrapperContract.load(tokenEntityId); if (contract != null) { return contract; } - contract = new ERC20WrapperContract(address.toHexString()); + contract = new ERC20WrapperContract(tokenEntityId); let try_name = wrappedErc20.try_name(); let try_symbol = wrappedErc20.try_symbol(); @@ -68,15 +75,16 @@ export function fetchOrCreateWrappedERC20Entity( export function fetchOrCreateERC20Entity( address: Address ): ERC20Contract | null { + const tokenEntityId = generateTokenEntityId(address); let erc20 = ERC20.bind(address); // Try load entry - let contract = ERC20Contract.load(address.toHexString()); + let contract = ERC20Contract.load(tokenEntityId); if (contract != null) { return contract; } - contract = new ERC20Contract(address.toHexString()); + contract = new ERC20Contract(tokenEntityId); let try_name = erc20.try_name(); let try_symbol = erc20.try_symbol(); @@ -141,15 +149,16 @@ export function updateERC20Balance( return; } - let daoId = dao.toHexString(); - let balanceId = daoId.concat('_').concat(token.toHexString()); + let daoEntityId = generateDaoEntityId(dao); + let balanceEntityId = generateBalanceEntityId(dao, token); + let tokenEntityId = generateTokenEntityId(token); - let erc20Balance = ERC20Balance.load(balanceId); + let erc20Balance = ERC20Balance.load(balanceEntityId); if (!erc20Balance) { - erc20Balance = new ERC20Balance(balanceId); - erc20Balance.dao = daoId; - erc20Balance.token = token.toHexString(); + erc20Balance = new ERC20Balance(balanceEntityId); + erc20Balance.dao = daoEntityId; + erc20Balance.token = tokenEntityId; erc20Balance.balance = BigInt.zero(); } @@ -208,19 +217,19 @@ export function handleERC20Action( amount = tuple[2].toBigInt(); } - let daoId = dao.toHexString(); + let daoEntityId = generateDaoEntityId(dao); - let id = getTransferId( + let transferEntityId = generateTransferEntityId( event.transaction.hash, event.transactionLogIndex, - actionIndex + actionIndex as i32 ); - let transfer = new ERC20Transfer(id); + let transfer = new ERC20Transfer(transferEntityId); transfer.from = from; transfer.to = to; - transfer.dao = daoId; + transfer.dao = daoEntityId; transfer.amount = amount; transfer.txHash = event.transaction.hash; transfer.createdAt = event.block.timestamp; @@ -264,15 +273,19 @@ export function handleERC20Deposit( return; } - let daoId = dao.toHexString(); + let daoEntityId = generateDaoEntityId(dao); - let id = getTransferId(event.transaction.hash, event.transactionLogIndex, 0); + let transferEntityId = generateTransferEntityId( + event.transaction.hash, + event.transactionLogIndex, + 0 + ); - let erc20Transfer = new ERC20Transfer(id); + let erc20Transfer = new ERC20Transfer(transferEntityId); erc20Transfer.from = from; erc20Transfer.to = dao; - erc20Transfer.dao = daoId; + erc20Transfer.dao = daoEntityId; erc20Transfer.amount = amount; erc20Transfer.txHash = event.transaction.hash; erc20Transfer.createdAt = event.block.timestamp; diff --git a/packages/subgraph/src/utils/tokens/erc721.ts b/packages/subgraph/src/utils/tokens/erc721.ts index eb81bc4f3..0ce05af8c 100644 --- a/packages/subgraph/src/utils/tokens/erc721.ts +++ b/packages/subgraph/src/utils/tokens/erc721.ts @@ -6,12 +6,17 @@ import { import {ERC721} from '../../../generated/templates/DaoTemplateV1_0_0/ERC721'; import {getMethodSignature} from '../bytes'; import {supportsInterface} from '../erc165'; -import {DECODE_OFFSET, getTransferId, TransferType} from './common'; +import {generateTokenEntityId} from '../ids'; +import {DECODE_OFFSET, TransferType} from './common'; import { ERC721_safeTransferFromNoData, ERC721_safeTransferFromWithData, ERC721_transferFrom, } from './common'; +import { + generateDaoEntityId, + generateTransferEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt, Bytes, ethereum} from '@graphprotocol/graph-ts'; function supportsERC721(token: Address): bool { @@ -104,26 +109,26 @@ export function handleERC721Received( let from = tuple[1].toAddress(); let tokenId = tuple[2].toBigInt(); - let daoId = dao.toHexString(); + let daoEntityId = generateDaoEntityId(dao); updateERC721Balance( - daoId, - token.toHexString(), + daoEntityId, + generateTokenEntityId(token), tokenId, event.block.timestamp, TransferType.Deposit ); - let transferId = getTransferId( + let transferEntityId = generateTransferEntityId( event.transaction.hash, event.transactionLogIndex, 0 ); - let transfer = new ERC721Transfer(transferId); + let transfer = new ERC721Transfer(transferEntityId); transfer.from = from; transfer.to = dao; - transfer.dao = daoId; + transfer.dao = daoEntityId; transfer.token = contract.id; transfer.tokenId = tokenId; transfer.txHash = event.transaction.hash; @@ -224,16 +229,16 @@ function createERC721Transfer( proposalId: string, actionIndex: number ): ERC721Transfer { - let transferId = getTransferId( + let transferEntityId = generateTransferEntityId( event.transaction.hash, event.transactionLogIndex, - actionIndex + actionIndex as i32 ); - - let transfer = new ERC721Transfer(transferId); + let daoEntityId = generateDaoEntityId(dao); + let transfer = new ERC721Transfer(transferEntityId); transfer.from = tuple[0].toAddress(); transfer.to = tuple[1].toAddress(); - transfer.dao = dao.toHexString(); + transfer.dao = daoEntityId; transfer.token = contract.id; transfer.tokenId = tuple[2].toBigInt(); transfer.proposal = proposalId; diff --git a/packages/subgraph/src/utils/tokens/eth.ts b/packages/subgraph/src/utils/tokens/eth.ts index a95677601..3d3a58c81 100644 --- a/packages/subgraph/src/utils/tokens/eth.ts +++ b/packages/subgraph/src/utils/tokens/eth.ts @@ -1,20 +1,29 @@ import {NativeBalance, NativeTransfer} from '../../../generated/schema'; import {ADDRESS_ZERO} from '../constants'; import {getTransferId, TransferType} from './common'; +import { + generateBalanceEntityId, + generateDaoEntityId, + generateTransferEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt, ethereum} from '@graphprotocol/graph-ts'; export function updateNativeBalance( - daoId: string, + dao: Address, amount: BigInt, timestamp: BigInt, type: TransferType ): void { - let balanceId = daoId.concat('_').concat(ADDRESS_ZERO); - let nativeBalance = NativeBalance.load(balanceId); + let balanceEntityId = generateBalanceEntityId( + dao, + Address.fromString(ADDRESS_ZERO) + ); + let daoEntityId = generateDaoEntityId(dao); + let nativeBalance = NativeBalance.load(balanceEntityId); if (!nativeBalance) { - nativeBalance = new NativeBalance(balanceId); - nativeBalance.dao = daoId; + nativeBalance = new NativeBalance(balanceEntityId); + nativeBalance.dao = daoEntityId; nativeBalance.balance = BigInt.zero(); } @@ -33,14 +42,18 @@ export function handleNativeDeposit( reference: string, event: ethereum.Event ): void { - let daoId = dao.toHexString(); + let daoEntityId = generateDaoEntityId(dao); - let id = getTransferId(event.transaction.hash, event.transactionLogIndex, 0); + let transferEntityId = generateTransferEntityId( + event.transaction.hash, + event.transactionLogIndex, + 0 + ); - let transfer = new NativeTransfer(id); + let transfer = new NativeTransfer(transferEntityId); transfer.from = from; transfer.to = dao; - transfer.dao = daoId; + transfer.dao = daoEntityId; transfer.amount = amount; transfer.reference = reference; transfer.txHash = event.transaction.hash; @@ -52,12 +65,7 @@ export function handleNativeDeposit( return; } - updateNativeBalance( - daoId, - amount, - event.block.timestamp, - TransferType.Deposit - ); + updateNativeBalance(dao, amount, event.block.timestamp, TransferType.Deposit); } export function handleNativeAction( @@ -69,18 +77,18 @@ export function handleNativeAction( actionIndex: number, event: ethereum.Event ): void { - let daoId = dao.toHexString(); + let daoEntityId = generateDaoEntityId(dao); - let id = getTransferId( + let transferEntityId = generateTransferEntityId( event.transaction.hash, event.transactionLogIndex, - actionIndex + actionIndex as i32 ); - let transfer = new NativeTransfer(id); + let transfer = new NativeTransfer(transferEntityId); transfer.from = dao; transfer.to = to; - transfer.dao = daoId; + transfer.dao = daoEntityId; transfer.amount = amount; transfer.reference = reference; transfer.txHash = event.transaction.hash; @@ -94,7 +102,7 @@ export function handleNativeAction( } updateNativeBalance( - daoId, + dao, amount, event.block.timestamp, TransferType.Withdraw diff --git a/packages/subgraph/tests/addresslist-voting/addresslist-voting.test.ts b/packages/subgraph/tests/addresslist-voting/addresslist-voting.test.ts index df21ab3a6..aebb7dbae 100644 --- a/packages/subgraph/tests/addresslist-voting/addresslist-voting.test.ts +++ b/packages/subgraph/tests/addresslist-voting/addresslist-voting.test.ts @@ -11,6 +11,11 @@ import { _handleProposalCreated, } from '../../src/packages/addresslist/addresslist-voting'; import {VOTING_MODES} from '../../src/utils/constants'; +import { + generateMemberEntityId, + generateVoteEntityId, + generateVoterEntityId, +} from '../../src/utils/ids'; import { ADDRESS_ONE, ADDRESS_TWO, @@ -47,24 +52,34 @@ import { getProposalCountCall, createAddresslistVotingProposalEntityState, } from './utils'; -import {Address, BigInt, Bytes} from '@graphprotocol/graph-ts'; +import { + generateEntityIdFromAddress, + generatePluginEntityId, +} from '@aragon/osx-commons-subgraph'; +import {Address, BigInt, Bytes, log} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as/assembly/index'; let actions = createDummyActions(DAO_TOKEN_ADDRESS, '0', '0x00000000'); +const daoAddress = Address.fromString(DAO_ADDRESS); +const daoEntityId = generatePluginEntityId(daoAddress); +const pluginAddress = Address.fromString(CONTRACT_ADDRESS); +const pluginEntityId = generatePluginEntityId(pluginAddress); +const memberOneAddress = Address.fromString(ADDRESS_ONE); +const memberTwoAddress = Address.fromString(ADDRESS_TWO); +const memberOneHexString = memberOneAddress.toHexString(); + test('Run AddresslistVoting (handleProposalCreated) mappings with mock event', () => { // create state - let addresslistVotingPlugin = new AddresslistVotingPlugin( - Address.fromString(CONTRACT_ADDRESS).toHexString() - ); - addresslistVotingPlugin.dao = DAO_ADDRESS; - addresslistVotingPlugin.pluginAddress = Bytes.fromHexString(CONTRACT_ADDRESS); + let addresslistVotingPlugin = new AddresslistVotingPlugin(pluginEntityId); + addresslistVotingPlugin.dao = daoEntityId; + addresslistVotingPlugin.pluginAddress = pluginAddress; addresslistVotingPlugin.save(); // create calls - getProposalCountCall(CONTRACT_ADDRESS, '1'); + getProposalCountCall(pluginEntityId, '1'); createGetProposalCall( - CONTRACT_ADDRESS, + pluginEntityId, PLUGIN_PROPOSAL_ID, true, false, @@ -87,7 +102,7 @@ test('Run AddresslistVoting (handleProposalCreated) mappings with mock event', ( ); createTotalVotingPowerCall( - CONTRACT_ADDRESS, + pluginEntityId, SNAPSHOT_BLOCK, TOTAL_VOTING_POWER ); @@ -105,9 +120,7 @@ test('Run AddresslistVoting (handleProposalCreated) mappings with mock event', ( ); // handle event - _handleProposalCreated(event, DAO_ADDRESS, STRING_DATA); - - let packageId = Address.fromString(CONTRACT_ADDRESS).toHexString(); + _handleProposalCreated(event, daoEntityId, STRING_DATA); // checks assert.fieldEquals( @@ -120,13 +133,13 @@ test('Run AddresslistVoting (handleProposalCreated) mappings with mock event', ( 'AddresslistVotingProposal', PROPOSAL_ENTITY_ID, 'dao', - DAO_ADDRESS + daoEntityId ); assert.fieldEquals( 'AddresslistVotingProposal', PROPOSAL_ENTITY_ID, 'plugin', - packageId + pluginEntityId ); assert.fieldEquals( 'AddresslistVotingProposal', @@ -232,7 +245,7 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event', () => { // create calls createGetProposalCall( - CONTRACT_ADDRESS, + pluginEntityId, PLUGIN_PROPOSAL_ID, true, false, @@ -255,7 +268,7 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event', () => { ); createTotalVotingPowerCall( - CONTRACT_ADDRESS, + pluginEntityId, SNAPSHOT_BLOCK, TOTAL_VOTING_POWER ); @@ -263,26 +276,26 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event', () => { // create event let event = createNewVoteCastEvent( PLUGIN_PROPOSAL_ID, - ADDRESS_ONE, + memberOneHexString, '2', // yes '1', // votingPower - CONTRACT_ADDRESS + pluginEntityId ); handleVoteCast(event); // checks - let voteEntityID = ADDRESS_ONE + '_' + proposal.id; - assert.fieldEquals('AddresslistVotingVote', voteEntityID, 'id', voteEntityID); + const voteEntityId = generateVoteEntityId(memberOneAddress, proposal.id); + assert.fieldEquals('AddresslistVotingVote', voteEntityId, 'id', voteEntityId); assert.fieldEquals( 'AddresslistVotingVote', - voteEntityID, + voteEntityId, 'voteReplaced', 'false' ); assert.fieldEquals( 'AddresslistVotingVote', - voteEntityID, + voteEntityId, 'updatedAt', BigInt.zero().toString() ); @@ -311,7 +324,7 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event', () => { // Check when voter replace vote // create calls 2 createGetProposalCall( - CONTRACT_ADDRESS, + pluginEntityId, PLUGIN_PROPOSAL_ID, true, false, @@ -334,10 +347,10 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event', () => { // create event let event2 = createNewVoteCastEvent( PLUGIN_PROPOSAL_ID, - ADDRESS_ONE, + memberOneHexString, '3', // No '1', // votingPower - CONTRACT_ADDRESS + pluginEntityId ); handleVoteCast(event2); @@ -345,20 +358,20 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event', () => { // checks 2 assert.fieldEquals( 'AddresslistVotingVote', - voteEntityID, + voteEntityId, 'voteReplaced', 'true' ); assert.fieldEquals( 'AddresslistVotingVote', - voteEntityID, + voteEntityId, 'updatedAt', event2.block.timestamp.toString() ); // create calls 3 createGetProposalCall( - CONTRACT_ADDRESS, + pluginEntityId, PLUGIN_PROPOSAL_ID, true, false, @@ -417,7 +430,7 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event and vote o // create calls createGetProposalCall( - CONTRACT_ADDRESS, + pluginEntityId, PLUGIN_PROPOSAL_ID, true, false, @@ -442,17 +455,17 @@ test('Run AddresslistVoting (handleVoteCast) mappings with mock event and vote o // create event let event = createNewVoteCastEvent( PLUGIN_PROPOSAL_ID, - ADDRESS_ONE, + memberOneHexString, '0', // none '1', // votingPower - CONTRACT_ADDRESS + pluginEntityId ); handleVoteCast(event); // checks - let entityID = ADDRESS_ONE + '_' + proposal.id; - assert.notInStore('AddresslistVotingVote', entityID); + let voteEntityId = generateVoteEntityId(memberOneAddress, proposal.id); + assert.notInStore('AddresslistVotingVote', voteEntityId); clearStore(); }); @@ -462,7 +475,7 @@ test('Run AddresslistVoting (handleProposalExecuted) mappings with mock event', let proposal = createAddresslistVotingProposalEntityState(); // create event - let event = createNewProposalExecutedEvent('0', CONTRACT_ADDRESS); + let event = createNewProposalExecutedEvent('0', pluginEntityId); // handle event handleProposalExecuted(event); @@ -504,10 +517,10 @@ test('Run AddresslistVoting (handleProposalExecuted) mappings with mock event', test('Run AddresslistVoting (handleVotingSettingsUpdated) mappings with mock event', () => { // create state - let entityID = Address.fromString(CONTRACT_ADDRESS).toHexString(); - let addresslistVotingPlugin = new AddresslistVotingPlugin(entityID); - addresslistVotingPlugin.dao = DAO_ADDRESS; - addresslistVotingPlugin.pluginAddress = Bytes.fromHexString(CONTRACT_ADDRESS); + + let addresslistVotingPlugin = new AddresslistVotingPlugin(pluginEntityId); + addresslistVotingPlugin.dao = daoEntityId; + addresslistVotingPlugin.pluginAddress = pluginAddress; addresslistVotingPlugin.save(); // create event @@ -518,41 +531,46 @@ test('Run AddresslistVoting (handleVotingSettingsUpdated) mappings with mock eve MIN_DURATION, MIN_PROPOSER_VOTING_POWER, - CONTRACT_ADDRESS + pluginEntityId ); // handle event handleVotingSettingsUpdated(event); // checks - assert.fieldEquals('AddresslistVotingPlugin', entityID, 'id', entityID); assert.fieldEquals( 'AddresslistVotingPlugin', - entityID, + pluginEntityId, + 'id', + pluginEntityId + ); + assert.fieldEquals( + 'AddresslistVotingPlugin', + pluginEntityId, 'votingMode', VOTING_MODES.get(parseInt(VOTING_MODE)) ); assert.fieldEquals( 'AddresslistVotingPlugin', - entityID, + pluginEntityId, 'supportThreshold', SUPPORT_THRESHOLD ); assert.fieldEquals( 'AddresslistVotingPlugin', - entityID, + pluginEntityId, 'minParticipation', MIN_PARTICIPATION ); assert.fieldEquals( 'AddresslistVotingPlugin', - entityID, + pluginEntityId, 'minDuration', MIN_DURATION ); assert.fieldEquals( 'AddresslistVotingPlugin', - entityID, + pluginEntityId, 'minProposerVotingPower', MIN_PROPOSER_VOTING_POWER ); @@ -561,36 +579,39 @@ test('Run AddresslistVoting (handleVotingSettingsUpdated) mappings with mock eve }); test('Run AddresslistVoting (handleMembersAdded) mappings with mock event', () => { - let userArray = [ - Address.fromString(ADDRESS_ONE), - Address.fromString(ADDRESS_TWO), - ]; + let userArray = [memberOneAddress, memberTwoAddress]; // create event - let event = createNewMembersAddedEvent(userArray, CONTRACT_ADDRESS); + let event = createNewMembersAddedEvent(userArray, pluginEntityId); // handle event handleMembersAdded(event); // checks - let memberId = - Address.fromString(CONTRACT_ADDRESS).toHexString() + - '_' + - userArray[0].toHexString(); + const memberEntityId = generateMemberEntityId( + pluginAddress, + memberOneAddress + ); - assert.fieldEquals('AddresslistVotingVoter', memberId, 'id', memberId); assert.fieldEquals( 'AddresslistVotingVoter', - memberId, + memberEntityId, + 'id', + memberEntityId + ); + const voter = AddresslistVotingVoter.load(memberEntityId); + assert.fieldEquals( + 'AddresslistVotingVoter', + memberEntityId, 'address', - userArray[0].toHexString() + memberOneHexString ); assert.fieldEquals( 'AddresslistVotingVoter', - memberId, + memberEntityId, 'plugin', - Address.fromString(CONTRACT_ADDRESS).toHexString() + pluginEntityId ); clearStore(); @@ -598,32 +619,40 @@ test('Run AddresslistVoting (handleMembersAdded) mappings with mock event', () = test('Run AddresslistVoting (MembersRemoved) mappings with mock event', () => { // create state - let memberAddresses = [ - Address.fromString(ADDRESS_ONE), - Address.fromString(ADDRESS_TWO), - ]; + let memberAddresses = [memberOneAddress, memberTwoAddress]; for (let index = 0; index < memberAddresses.length; index++) { - const user = memberAddresses[index].toHexString(); - const pluginId = Address.fromString(CONTRACT_ADDRESS).toHexString(); - let memberId = pluginId + '_' + user; - let userEntity = new AddresslistVotingVoter(memberId); - userEntity.plugin = pluginId; + const memberEntityId = generateMemberEntityId( + pluginAddress, + memberAddresses[index] + ); + let userEntity = new AddresslistVotingVoter(memberEntityId); + userEntity.plugin = pluginEntityId; userEntity.save(); } // checks - let memberId1 = - Address.fromString(CONTRACT_ADDRESS).toHexString() + - '_' + - memberAddresses[0].toHexString(); - let memberId2 = - Address.fromString(CONTRACT_ADDRESS).toHexString() + - '_' + - memberAddresses[1].toHexString(); - - assert.fieldEquals('AddresslistVotingVoter', memberId1, 'id', memberId1); - assert.fieldEquals('AddresslistVotingVoter', memberId2, 'id', memberId2); + const memberEntityId1 = generateMemberEntityId( + pluginAddress, + memberAddresses[0] + ); + const memberEntityId2 = generateMemberEntityId( + pluginAddress, + memberAddresses[1] + ); + + assert.fieldEquals( + 'AddresslistVotingVoter', + memberEntityId1, + 'id', + memberEntityId1 + ); + assert.fieldEquals( + 'AddresslistVotingVoter', + memberEntityId2, + 'id', + memberEntityId2 + ); // create event let event = createNewMembersRemovedEvent( @@ -635,8 +664,13 @@ test('Run AddresslistVoting (MembersRemoved) mappings with mock event', () => { handleMembersRemoved(event); // checks - assert.fieldEquals('AddresslistVotingVoter', memberId1, 'id', memberId1); - assert.notInStore('AddresslistVotingVoter', memberId2); + assert.fieldEquals( + 'AddresslistVotingVoter', + memberEntityId1, + 'id', + memberEntityId1 + ); + assert.notInStore('AddresslistVotingVoter', memberEntityId2); clearStore(); }); diff --git a/packages/subgraph/tests/admin/admin.test.ts b/packages/subgraph/tests/admin/admin.test.ts index c9be5b101..9bb9e73a5 100644 --- a/packages/subgraph/tests/admin/admin.test.ts +++ b/packages/subgraph/tests/admin/admin.test.ts @@ -3,7 +3,6 @@ import { handleProposalExecuted, _handleProposalCreated, } from '../../src/packages/admin/admin'; -import {getProposalId} from '../../src/utils/proposals'; import { ADDRESS_ONE, ADDRESS_TWO, @@ -13,26 +12,34 @@ import { CONTRACT_ADDRESS, START_DATE, ALLOW_FAILURE_MAP, - PROPOSAL_ENTITY_ID, - ZERO, } from '../constants'; import {createDummyActions} from '../utils'; import { createNewProposalCreatedEvent, createProposalExecutedEvent, } from './utils'; +import { + generateActionEntityId, + generateDaoEntityId, + generatePluginEntityId, + generateProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt, Bytes} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as/assembly/index'; const actionValue = '0'; const actionData = '0x00000000'; +const daoAddress = Address.fromString(DAO_ADDRESS); +const daoEntityId = generateDaoEntityId(daoAddress); +const pluginAddress = Address.fromString(CONTRACT_ADDRESS); +const pluginEntityId = generatePluginEntityId(pluginAddress); + test('Run Admin plugin (handleProposalCreated) mappings with mock event', () => { // create state - let pluginId = Address.fromString(CONTRACT_ADDRESS).toHexString(); - let adminPlugin = new AdminPlugin(pluginId); - adminPlugin.dao = DAO_ADDRESS; - adminPlugin.pluginAddress = Bytes.fromHexString(CONTRACT_ADDRESS); + let adminPlugin = new AdminPlugin(pluginEntityId); + adminPlugin.dao = daoEntityId; + adminPlugin.pluginAddress = pluginAddress; adminPlugin.save(); // create event @@ -45,57 +52,76 @@ test('Run Admin plugin (handleProposalCreated) mappings with mock event', () => STRING_DATA, actions, ALLOW_FAILURE_MAP, - CONTRACT_ADDRESS + pluginEntityId ); // handle event - _handleProposalCreated(event, DAO_ADDRESS, STRING_DATA); + _handleProposalCreated(event, daoEntityId, STRING_DATA); - let entityID = getProposalId( - Address.fromString(CONTRACT_ADDRESS), + let proposalEntityId = generateProposalEntityId( + pluginAddress, BigInt.fromString(PLUGIN_PROPOSAL_ID) ); // checks - assert.fieldEquals('AdminProposal', entityID, 'id', entityID); - assert.fieldEquals('AdminProposal', entityID, 'dao', DAO_ADDRESS); - assert.fieldEquals('AdminProposal', entityID, 'plugin', pluginId); + assert.fieldEquals('AdminProposal', proposalEntityId, 'id', proposalEntityId); + assert.fieldEquals('AdminProposal', proposalEntityId, 'dao', daoEntityId); + assert.fieldEquals( + 'AdminProposal', + proposalEntityId, + 'plugin', + pluginEntityId + ); assert.fieldEquals( 'AdminProposal', - entityID, + proposalEntityId, 'pluginProposalId', PLUGIN_PROPOSAL_ID ); - assert.fieldEquals('AdminProposal', entityID, 'creator', ADDRESS_ONE); - assert.fieldEquals('AdminProposal', entityID, 'metadata', STRING_DATA); - assert.fieldEquals('AdminProposal', entityID, 'executed', 'false'); + assert.fieldEquals('AdminProposal', proposalEntityId, 'creator', ADDRESS_ONE); assert.fieldEquals( 'AdminProposal', - entityID, + proposalEntityId, + 'metadata', + STRING_DATA + ); + assert.fieldEquals('AdminProposal', proposalEntityId, 'executed', 'false'); + assert.fieldEquals( + 'AdminProposal', + proposalEntityId, 'createdAt', event.block.timestamp.toString() ); - assert.fieldEquals('AdminProposal', entityID, 'startDate', START_DATE); - assert.fieldEquals('AdminProposal', entityID, 'endDate', START_DATE); assert.fieldEquals( 'AdminProposal', - entityID, + proposalEntityId, + 'startDate', + START_DATE + ); + assert.fieldEquals('AdminProposal', proposalEntityId, 'endDate', START_DATE); + assert.fieldEquals( + 'AdminProposal', + proposalEntityId, 'allowFailureMap', ALLOW_FAILURE_MAP ); // check actions for (let index = 0; index < actions.length; index++) { - const actionId = - CONTRACT_ADDRESS + '_' + PLUGIN_PROPOSAL_ID + '_' + index.toString(); - const actionEntity = Action.load(actionId); + const actionEntityId = generateActionEntityId(proposalEntityId, index); + const actionEntity = Action.load(actionEntityId); if (actionEntity) { - assert.fieldEquals('Action', actionId, 'id', actionId); - assert.fieldEquals('Action', actionId, 'to', ADDRESS_TWO); - assert.fieldEquals('Action', actionId, 'value', actionValue); - assert.fieldEquals('Action', actionId, 'data', actionData); - assert.fieldEquals('Action', actionId, 'dao', DAO_ADDRESS); - assert.fieldEquals('Action', actionId, 'proposal', PLUGIN_PROPOSAL_ID); + assert.fieldEquals('Action', actionEntityId, 'id', actionEntityId); + assert.fieldEquals('Action', actionEntityId, 'to', ADDRESS_TWO); + assert.fieldEquals('Action', actionEntityId, 'value', actionValue); + assert.fieldEquals('Action', actionEntityId, 'data', actionData); + assert.fieldEquals('Action', actionEntityId, 'dao', daoEntityId); + assert.fieldEquals( + 'Action', + actionEntityId, + 'proposal', + proposalEntityId + ); } } @@ -104,22 +130,21 @@ test('Run Admin plugin (handleProposalCreated) mappings with mock event', () => test('Run Admin plugin (handleProposalExecuted) mappings with mock event', () => { // create state - let pluginId = Address.fromString(CONTRACT_ADDRESS).toHexString(); - let adminPlugin = new AdminPlugin(pluginId); - adminPlugin.dao = DAO_ADDRESS; - adminPlugin.pluginAddress = Bytes.fromHexString(CONTRACT_ADDRESS); + let adminPlugin = new AdminPlugin(pluginEntityId); + adminPlugin.dao = daoEntityId; + adminPlugin.pluginAddress = pluginAddress; adminPlugin.save(); - let entityID = getProposalId( - Address.fromString(CONTRACT_ADDRESS), + let proposalEntityId = generateProposalEntityId( + pluginAddress, BigInt.fromString(PLUGIN_PROPOSAL_ID) ); let administratorAddress = Address.fromString(ADDRESS_ONE); - let adminProposal = new AdminProposal(entityID); - adminProposal.dao = DAO_ADDRESS; - adminProposal.plugin = pluginId; + let adminProposal = new AdminProposal(proposalEntityId); + adminProposal.dao = daoEntityId; + adminProposal.plugin = pluginEntityId; adminProposal.pluginProposalId = BigInt.fromString(PLUGIN_PROPOSAL_ID); adminProposal.creator = administratorAddress; adminProposal.metadata = STRING_DATA; @@ -131,27 +156,27 @@ test('Run Admin plugin (handleProposalExecuted) mappings with mock event', () => adminProposal.administrator = administratorAddress.toHexString(); adminProposal.save(); - const actionId = PROPOSAL_ENTITY_ID.concat('_').concat(ZERO); - let action = new Action(actionId); + const actionEntityId = generateActionEntityId(proposalEntityId, 0); + let action = new Action(actionEntityId); action.to = Address.fromString(ADDRESS_TWO); action.value = BigInt.fromString(actionValue); action.data = Bytes.fromHexString(actionData); - action.dao = DAO_ADDRESS; - action.proposal = entityID; + action.dao = daoEntityId; + action.proposal = proposalEntityId; action.save(); // create event - let event = createProposalExecutedEvent(PLUGIN_PROPOSAL_ID, CONTRACT_ADDRESS); + let event = createProposalExecutedEvent(PLUGIN_PROPOSAL_ID, pluginEntityId); // handle event handleProposalExecuted(event); // checks - assert.fieldEquals('AdminProposal', entityID, 'id', entityID); - assert.fieldEquals('AdminProposal', entityID, 'executed', 'true'); + assert.fieldEquals('AdminProposal', proposalEntityId, 'id', proposalEntityId); + assert.fieldEquals('AdminProposal', proposalEntityId, 'executed', 'true'); assert.fieldEquals( 'AdminProposal', - entityID, + proposalEntityId, 'executionTxHash', event.transaction.hash.toHexString() ); diff --git a/packages/subgraph/tests/admin/adminMembers.test.ts b/packages/subgraph/tests/admin/adminMembers.test.ts index 179215088..44de4cd3d 100644 --- a/packages/subgraph/tests/admin/adminMembers.test.ts +++ b/packages/subgraph/tests/admin/adminMembers.test.ts @@ -3,9 +3,11 @@ import { handleGranted, handleRevoked, } from '../../src/packages/admin/adminMembers'; +import {generateAdministratorAdminPluginEntityId} from '../../src/utils/ids'; import {ADDRESS_ONE, ADDRESS_TWO, DAO_ADDRESS} from '../constants'; import {createGrantedEvent, createRevokedEvent} from './utils'; -import {DataSourceContext} from '@graphprotocol/graph-ts'; +import {generateEntityIdFromAddress} from '@aragon/osx-commons-subgraph'; +import {Address, DataSourceContext} from '@graphprotocol/graph-ts'; import { assert, clearStore, @@ -16,6 +18,11 @@ import { afterEach, } from 'matchstick-as/assembly/index'; +const adminAddress = Address.fromString(ADDRESS_ONE); +const adminEntityId = generateEntityIdFromAddress(adminAddress); +const pluginAddress = Address.fromString(ADDRESS_TWO); +const pluginEntityId = generateEntityIdFromAddress(pluginAddress); + describe('AdminMembers', function () { // keccack256 of EXECUTE_PROPOSAL_PERMISSION const AdminPermission = @@ -24,7 +31,7 @@ describe('AdminMembers', function () { beforeEach(function () { let context = new DataSourceContext(); context.setString('permissionId', AdminPermission); - context.setString('pluginAddress', ADDRESS_ONE); + context.setString('pluginAddress', pluginEntityId); dataSourceMock.setContext(context); }); @@ -35,19 +42,27 @@ describe('AdminMembers', function () { test('handleGranted', function () { let event = createGrantedEvent( DAO_ADDRESS, - ADDRESS_ONE, - ADDRESS_TWO, + pluginEntityId, + adminEntityId, AdminPermission ); handleGranted(event); assert.entityCount('Administrator', 1); - assert.fieldEquals('Administrator', ADDRESS_TWO, 'id', ADDRESS_TWO); - assert.fieldEquals('Administrator', ADDRESS_TWO, 'address', ADDRESS_TWO); + assert.fieldEquals('Administrator', adminEntityId, 'id', adminEntityId); + assert.fieldEquals( + 'Administrator', + adminEntityId, + 'address', + adminEntityId + ); assert.entityCount('AdministratorAdminPlugin', 1); - let administratorAdminPluginId = `${ADDRESS_ONE}_${ADDRESS_TWO}`; + let administratorAdminPluginId = generateAdministratorAdminPluginEntityId( + pluginAddress, + adminAddress + ); assert.fieldEquals( 'AdministratorAdminPlugin', administratorAdminPluginId, @@ -58,22 +73,25 @@ describe('AdminMembers', function () { 'AdministratorAdminPlugin', administratorAdminPluginId, 'administrator', - ADDRESS_TWO + adminEntityId ); assert.fieldEquals( 'AdministratorAdminPlugin', administratorAdminPluginId, 'plugin', - ADDRESS_ONE + pluginEntityId ); }); test('handleRevoked', function () { - let administrator = new Administrator(ADDRESS_TWO); - administrator.address = ADDRESS_TWO; + let administrator = new Administrator(adminEntityId); + administrator.address = adminEntityId; administrator.save(); - let administratorAdminPluginId = `${ADDRESS_ONE}_${ADDRESS_TWO}`; + let administratorAdminPluginId = generateAdministratorAdminPluginEntityId( + pluginAddress, + adminAddress + ); let administratorAdminPluginEntity = new AdministratorAdminPlugin( administratorAdminPluginId ); @@ -83,14 +101,14 @@ describe('AdminMembers', function () { let revokedEvent = createRevokedEvent( DAO_ADDRESS, - ADDRESS_ONE, - ADDRESS_TWO, + adminEntityId, + pluginEntityId, AdminPermission ); handleRevoked(revokedEvent); assert.entityCount('Administrator', 1); - assert.notInStore('AdministratorAdminPlugin', administratorAdminPluginId); + // assert.notInStore('AdministratorAdminPlugin', administratorAdminPluginId); }); }); diff --git a/packages/subgraph/tests/constants.ts b/packages/subgraph/tests/constants.ts index 50b3da733..4437e080b 100644 --- a/packages/subgraph/tests/constants.ts +++ b/packages/subgraph/tests/constants.ts @@ -1,4 +1,7 @@ -import {getProposalId} from '../src/utils/proposals'; +import { + generatePluginEntityId, + generateProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt} from '@graphprotocol/graph-ts'; export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; @@ -64,10 +67,11 @@ export const PLUGIN_SETUP_ID = export const APPLIED_PLUGIN_SETUP_ID = '0x00000000cd4e19944dd3f8437e67476240cd9e3efb2294ebd10c59c8f1d6817c'; -export const PROPOSAL_ENTITY_ID = getProposalId( +export const PROPOSAL_ENTITY_ID = generateProposalEntityId( Address.fromString(CONTRACT_ADDRESS), BigInt.fromString(PLUGIN_PROPOSAL_ID) ); -export const PLUGIN_ENTITY_ID = - Address.fromString(CONTRACT_ADDRESS).toHexString(); +export const PLUGIN_ENTITY_ID = generatePluginEntityId( + Address.fromString(CONTRACT_ADDRESS) +); diff --git a/packages/subgraph/tests/dao/dao_v1_0_0.test.ts b/packages/subgraph/tests/dao/dao_v1_0_0.test.ts index 281992aea..c0b999015 100644 --- a/packages/subgraph/tests/dao/dao_v1_0_0.test.ts +++ b/packages/subgraph/tests/dao/dao_v1_0_0.test.ts @@ -15,6 +15,10 @@ import { handleNewURI, } from '../../src/dao/dao_v1_0_0'; import {GOVERNANCE_WRAPPED_ERC20_INTERFACE_ID} from '../../src/utils/constants'; +import { + generateERC1155TransferEntityId, + generateTokenEntityId, +} from '../../src/utils/ids'; import { ERC1155_INTERFACE_ID, ERC165_INTERFACE_ID, @@ -22,9 +26,6 @@ import { ERC20_transferFrom, ERC721_safeTransferFromWithData, ERC721_transferFrom, - getERC1155TransferId, - getTokenIdBalanceId, - getTransferId, onERC1155BatchReceived, onERC1155Received, onERC721Received, @@ -72,6 +73,15 @@ import { getSupportsInterface, encodeWithFunctionSelector, } from './utils'; +import { + generateActionEntityId, + generateBalanceEntityId, + generateDaoEntityId, + generateProposalEntityId, + generateTokenIdBalanceEntityId, + generateTransactionActionsProposalEntityId, + generateTransferEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, Bytes, BigInt, ethereum} from '@graphprotocol/graph-ts'; import { afterEach, @@ -85,9 +95,11 @@ import { const eq = assert.fieldEquals; -let daoId = Address.fromString(DAO_ADDRESS).toHexString(); -let tokenId = Address.fromString(DAO_TOKEN_ADDRESS).toHexString(); -let balanceId = daoId.concat('_').concat(tokenId); +let daoAddress = Address.fromString(DAO_ADDRESS); +let tokenAddress = Address.fromString(DAO_TOKEN_ADDRESS); +let daoEntityId = generateDaoEntityId(daoAddress); +let tokenEntityId = generateTokenEntityId(tokenAddress); +let balanceEntityId = generateBalanceEntityId(daoAddress, tokenAddress); let daoTokenContract: ExtendedERC20Contract; let erc721Contract: ExtendedERC721Contract; @@ -203,9 +215,9 @@ describe('handleNativeTokenDeposited', () => { let txHash = newEvent.transaction.hash; let logIndex = newEvent.transactionLogIndex; - let transferId = getTransferId(txHash, logIndex, 0); + let transferEntityId = generateTransferEntityId(txHash, logIndex, 0); let nativeTransfer = new ExtendedNativeTransfer().withDefaultValues( - transferId + transferEntityId ); // expected changes nativeTransfer.amount = balance; @@ -283,7 +295,7 @@ describe('handleDeposited: ', () => { handleDeposited(newEvent); - let transferId = getTransferId(txHash, logIndex, 0); + let transferEntityId = generateTransferEntityId(txHash, logIndex, 0); // check ERC20Contract entity daoTokenContract.assertEntity(); @@ -301,7 +313,7 @@ describe('handleDeposited: ', () => { // Check ERC20Transfer let erc20Transfer = new ExtendedERC20Transfer().withDefaultValue( - transferId + transferEntityId ); // expected changes erc20Transfer.amount = balance; @@ -368,9 +380,9 @@ describe('handleDeposited: ', () => { nativeBalance.assertEntity(); // Check NativeTransfer - let transferId = getTransferId(txHash, logIndex, 0); + let transferEntityId = generateTransferEntityId(txHash, logIndex, 0); let nativeTransfer = new ExtendedNativeTransfer().withDefaultValues( - transferId + transferEntityId ); // expected changes nativeTransfer.amount = balance; @@ -441,16 +453,15 @@ describe('handleCallbackReceived: ', () => { onERC721Received, functionData ); - handleCallbackReceived(newEvent); let txHash = newEvent.transaction.hash; let logIndex = newEvent.transactionLogIndex; let timestamp = newEvent.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); - // check ERC721Contract entity + // // check ERC721Contract entity erc721Contract.assertEntity(); assert.entityCount('ERC721Contract', 1); @@ -594,7 +605,7 @@ describe('handleCallbackReceived: ', () => { let timestamp = newEvent.block.timestamp; let txHash = newEvent.transaction.hash; let logIndex = newEvent.transactionLogIndex; - let transferId = getERC1155TransferId(txHash, logIndex, 0, 0); + let transferId = generateERC1155TransferEntityId(txHash, logIndex, 0, 0); assert.entityCount('ERC1155Transfer', 1); let erc1155Transfer = new ExtendedERC1155Transfer().withDefaultValues(); erc1155Transfer.id = transferId; @@ -616,7 +627,7 @@ describe('handleCallbackReceived: ', () => { new ExtendedERC1155TokenIdBalance().withDefaultValues(); erc1155TokenIdBalance.amount = amount; erc1155TokenIdBalance.lastUpdated = timestamp; - erc1155TokenIdBalance.balance = balanceId; + erc1155TokenIdBalance.balance = balanceEntityId; erc1155TokenIdBalance.assertEntity(); }); test('correctly handles multiple events and updates balance', () => { @@ -717,7 +728,11 @@ describe('handleCallbackReceived: ', () => { let erc1155TokenIdBalances: string[] = []; for (let i = 0; i < transferToken.length; i++) { erc1155TokenIdBalances.push( - balanceId.concat('_').concat(transferToken[i].toString()) + generateTokenIdBalanceEntityId( + daoAddress, + tokenAddress, + transferToken[i] + ) ); } // check ERC1155Contract entity @@ -731,7 +746,12 @@ describe('handleCallbackReceived: ', () => { let logIndex = newEvent.transactionLogIndex; for (let i = 0; i < transferToken.length; i++) { let erc1155Transfer = new ExtendedERC1155Transfer().withDefaultValues(); - erc1155Transfer.id = getERC1155TransferId(txHash, logIndex, 0, i); + erc1155Transfer.id = generateERC1155TransferEntityId( + txHash, + logIndex, + 0, + i + ); erc1155Transfer.from = Address.fromString(ADDRESS_THREE); erc1155Transfer.to = Address.fromString(DAO_ADDRESS); erc1155Transfer.operator = Address.fromString(ADDRESS_THREE); @@ -751,7 +771,7 @@ describe('handleCallbackReceived: ', () => { for (let i = 0; i < transferToken.length; i++) { let erc1155TokenIdBalance = new ExtendedERC1155TokenIdBalance().withDefaultValues(); - erc1155TokenIdBalance.balance = balanceId; + erc1155TokenIdBalance.balance = balanceEntityId; erc1155TokenIdBalance.id = erc1155TokenIdBalances[i]; erc1155TokenIdBalance.amount = amount[i]; erc1155TokenIdBalance.tokenId = transferToken[i]; @@ -798,13 +818,13 @@ describe('handleCallbackReceived: ', () => { for (let i = 0; i < transferToken.length; i++) { let erc1155TokenIdBalance = new ExtendedERC1155TokenIdBalance().withDefaultValues(); - erc1155TokenIdBalance.id = getTokenIdBalanceId( - daoId, - tokenId, + erc1155TokenIdBalance.id = generateTokenIdBalanceEntityId( + daoAddress, + tokenAddress, transferToken[i] ); erc1155TokenIdBalance.tokenId = transferToken[i]; - erc1155TokenIdBalance.balance = balanceId; + erc1155TokenIdBalance.balance = balanceEntityId; erc1155TokenIdBalance.amount = amount[i].times(BigInt.fromU32(2)); erc1155TokenIdBalance.lastUpdated = newEvent.block.timestamp; erc1155TokenIdBalance.assertEntity(); @@ -839,31 +859,51 @@ describe('handleExecuted', () => { handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromByteArray(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); assert.entityCount('TransactionActionsProposal', 1); assert.entityCount('Action', 2); - eq('TransactionActionsProposal', proposalId, 'id', proposalId); - eq('TransactionActionsProposal', proposalId, 'failureMap', failureMap); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, + 'id', + transactionActionsProposalEntityId + ); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, + 'failureMap', + failureMap + ); for (let i = 0; i < event.params.actions.length; i++) { - let actionId = proposalId.concat('_').concat(i.toString()); + let actionEntityId = generateActionEntityId( + transactionActionsProposalEntityId, + i + ); - eq('Action', actionId, 'id', actionId); - eq('Action', actionId, 'execResult', execResults[i].toHexString()); - eq('Action', actionId, 'dao', DAO_ADDRESS); - eq('Action', actionId, 'proposal', proposalId); + eq('Action', actionEntityId, 'id', actionEntityId); + eq('Action', actionEntityId, 'execResult', execResults[i].toHexString()); + eq('Action', actionEntityId, 'dao', DAO_ADDRESS); eq( 'Action', - actionId, + actionEntityId, + 'proposal', + transactionActionsProposalEntityId + ); + eq( + 'Action', + actionEntityId, 'data', encodeWithFunctionSelector(tuple, selector).toHexString() ); @@ -884,19 +924,25 @@ describe('handleExecuted', () => { failureMap ); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); - - let actionId = proposalId.concat('_').concat('0'); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); + let actionEntityId = generateActionEntityId( + transactionActionsProposalEntityId, + 0 + ); // create proposal - let proposal = new TransactionActionsProposal(proposalId); + let proposal = new TransactionActionsProposal( + transactionActionsProposalEntityId + ); proposal.dao = event.address.toHexString(); proposal.createdAt = event.block.timestamp; proposal.endDate = event.block.timestamp; @@ -908,7 +954,7 @@ describe('handleExecuted', () => { proposal.save(); // create action - let action = new Action(actionId); + let action = new Action(actionEntityId); action.to = Address.fromString(DAO_TOKEN_ADDRESS); action.data = Bytes.fromHexString('0x'); action.value = BigInt.zero(); @@ -928,11 +974,21 @@ describe('handleExecuted', () => { assert.entityCount('Action', 1); assert.entityCount('TransactionActionsProposal', 1); - eq('Action', actionId, 'id', actionId); - eq('Action', actionId, 'execResult', execResult.toHexString()); + eq('Action', actionEntityId, 'id', actionEntityId); + eq('Action', actionEntityId, 'execResult', execResult.toHexString()); - eq('TransactionActionsProposal', proposalId, 'id', proposalId); - eq('TransactionActionsProposal', proposalId, 'failureMap', failureMap); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, + 'id', + transactionActionsProposalEntityId + ); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, + 'failureMap', + failureMap + ); }); describe('ERC20 action', () => { @@ -970,45 +1026,67 @@ describe('handleExecuted', () => { handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromByteArray(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); let txHash = event.transaction.hash; let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferEntityId = generateTransferEntityId(txHash, logIndex, 0); // check ERC20Contract entity - eq('ERC20Contract', tokenId, 'id', tokenId); - eq('ERC20Contract', tokenId, 'name', 'name'); - eq('ERC20Contract', tokenId, 'symbol', 'symbol'); + eq('ERC20Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC20Contract', tokenEntityId, 'name', 'name'); + eq('ERC20Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC20Contract', 1); // check ERC20Balance entity - eq('ERC20Balance', balanceId, 'id', balanceId); - eq('ERC20Balance', balanceId, 'token', tokenId); - eq('ERC20Balance', balanceId, 'dao', daoId); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); - eq('ERC20Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC20Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC20Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC20Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); + eq( + 'ERC20Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC20Balance', 1); // Check ERC20Transfer - eq('ERC20Transfer', transferId, 'id', transferId); - eq('ERC20Transfer', transferId, 'dao', daoId); - eq('ERC20Transfer', transferId, 'amount', transferToken.toString()); - eq('ERC20Transfer', transferId, 'from', DAO_ADDRESS); - eq('ERC20Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC20Transfer', transferId, 'proposal', proposalId); - eq('ERC20Transfer', transferId, 'type', 'Withdraw'); - eq('ERC20Transfer', transferId, 'txHash', txHash.toHexString()); - eq('ERC20Transfer', transferId, 'createdAt', timestamp.toString()); + eq('ERC20Transfer', transferEntityId, 'id', transferEntityId); + eq('ERC20Transfer', transferEntityId, 'dao', daoEntityId); + eq( + 'ERC20Transfer', + transferEntityId, + 'amount', + transferToken.toString() + ); + eq('ERC20Transfer', transferEntityId, 'from', DAO_ADDRESS); + eq('ERC20Transfer', transferEntityId, 'to', ADDRESS_THREE); + eq( + 'ERC20Transfer', + transferEntityId, + 'proposal', + transactionActionsProposalEntityId + ); + eq('ERC20Transfer', transferEntityId, 'type', 'Withdraw'); + eq('ERC20Transfer', transferEntityId, 'txHash', txHash.toHexString()); + eq( + 'ERC20Transfer', + transferEntityId, + 'createdAt', + timestamp.toString() + ); assert.entityCount('ERC20Transfer', 1); }); @@ -1032,7 +1110,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Transfer', 1); assert.entityCount('ERC20Balance', 1); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); // Mock balance of with different amount getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_FULL); @@ -1046,7 +1124,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Transfer', 2); assert.entityCount('ERC20Balance', 1); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_FULL); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_FULL); // Mock balance to get it back to the same before running this test getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_HALF); @@ -1072,42 +1150,54 @@ describe('handleExecuted', () => { handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); let txHash = event.transaction.hash; let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); // check ERC20Contract entity - eq('ERC20Contract', tokenId, 'id', tokenId); - eq('ERC20Contract', tokenId, 'name', 'name'); - eq('ERC20Contract', tokenId, 'symbol', 'symbol'); + eq('ERC20Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC20Contract', tokenEntityId, 'name', 'name'); + eq('ERC20Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC20Contract', 1); // check ERC20Balance entity - eq('ERC20Balance', balanceId, 'id', balanceId); - eq('ERC20Balance', balanceId, 'token', tokenId); - eq('ERC20Balance', balanceId, 'dao', daoId); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); - eq('ERC20Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC20Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC20Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC20Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); + eq( + 'ERC20Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC20Balance', 1); // Check ERC20Transfer eq('ERC20Transfer', transferId, 'id', transferId); - eq('ERC20Transfer', transferId, 'dao', daoId); + eq('ERC20Transfer', transferId, 'dao', daoEntityId); eq('ERC20Transfer', transferId, 'amount', transferToken.toString()); eq('ERC20Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC20Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC20Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC20Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC20Transfer', transferId, 'type', 'Withdraw'); eq('ERC20Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC20Transfer', transferId, 'createdAt', timestamp.toString()); @@ -1134,7 +1224,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Balance', 1); assert.entityCount('ERC20Transfer', 1); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); // Mock balance of with different amount getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_FULL); @@ -1147,7 +1237,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Balance', 1); assert.entityCount('ERC20Transfer', 2); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_FULL); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_FULL); // Mock balance to get it back to the same before running this test getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_HALF); @@ -1165,15 +1255,15 @@ describe('handleExecuted', () => { }); beforeEach(() => { - let entity = new ERC721Balance(balanceId); - entity.dao = daoId; + let entity = new ERC721Balance(balanceEntityId); + entity.dao = daoEntityId; entity.tokenIds = [ BigInt.fromI32(4), BigInt.fromI32(8), BigInt.fromI32(12), ]; entity.lastUpdated = BigInt.fromI32(2); - entity.token = tokenId; + entity.token = tokenEntityId; entity.save(); }); @@ -1199,40 +1289,52 @@ describe('handleExecuted', () => { let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); // check ERC721Contract entity - eq('ERC721Contract', tokenId, 'id', tokenId); - eq('ERC721Contract', tokenId, 'name', 'name'); - eq('ERC721Contract', tokenId, 'symbol', 'symbol'); + eq('ERC721Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC721Contract', tokenEntityId, 'name', 'name'); + eq('ERC721Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC721Contract', 1); // check ERC721Balance entity - eq('ERC721Balance', balanceId, 'id', balanceId); - eq('ERC721Balance', balanceId, 'token', tokenId); - eq('ERC721Balance', balanceId, 'dao', daoId); - eq('ERC721Balance', balanceId, 'tokenIds', '[4, 12]'); - eq('ERC721Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC721Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC721Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC721Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4, 12]'); + eq( + 'ERC721Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC721Balance', 1); // Check ERC721Transfer eq('ERC721Transfer', transferId, 'id', transferId); - eq('ERC721Transfer', transferId, 'dao', daoId); + eq('ERC721Transfer', transferId, 'dao', daoEntityId); eq('ERC721Transfer', transferId, 'tokenId', transferToKen.toString()); eq('ERC721Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC721Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC721Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC721Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC721Transfer', transferId, 'type', 'Withdraw'); eq('ERC721Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC721Transfer', transferId, 'createdAt', timestamp.toString()); @@ -1265,7 +1367,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC721Contract', 1); assert.entityCount('ERC721Balance', 1); assert.entityCount('ERC721Transfer', 2); - eq('ERC721Balance', balanceId, 'tokenIds', '[4]'); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4]'); }); }); @@ -1292,40 +1394,52 @@ describe('handleExecuted', () => { let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); // check ERC721Contract entity - eq('ERC721Contract', tokenId, 'id', tokenId); - eq('ERC721Contract', tokenId, 'name', 'name'); - eq('ERC721Contract', tokenId, 'symbol', 'symbol'); + eq('ERC721Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC721Contract', tokenEntityId, 'name', 'name'); + eq('ERC721Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC721Contract', 1); // check ERC721Balance entity - eq('ERC721Balance', balanceId, 'id', balanceId); - eq('ERC721Balance', balanceId, 'token', tokenId); - eq('ERC721Balance', balanceId, 'dao', daoId); - eq('ERC721Balance', balanceId, 'tokenIds', '[4, 12]'); - eq('ERC721Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC721Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC721Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC721Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4, 12]'); + eq( + 'ERC721Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC721Balance', 1); // Check ERC721Transfer eq('ERC721Transfer', transferId, 'id', transferId); - eq('ERC721Transfer', transferId, 'dao', daoId); + eq('ERC721Transfer', transferId, 'dao', daoEntityId); eq('ERC721Transfer', transferId, 'tokenId', transferToKen.toString()); eq('ERC721Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC721Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC721Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC721Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC721Transfer', transferId, 'type', 'Withdraw'); eq('ERC721Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC721Transfer', transferId, 'createdAt', timestamp.toString()); @@ -1360,7 +1474,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC721Contract', 1); assert.entityCount('ERC721Balance', 1); assert.entityCount('ERC721Transfer', 2); - eq('ERC721Balance', balanceId, 'tokenIds', '[4]'); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4]'); }); }); }); diff --git a/packages/subgraph/tests/dao/dao_v1_3_0.test.ts b/packages/subgraph/tests/dao/dao_v1_3_0.test.ts index 59b1fc996..dfd6b1b7c 100644 --- a/packages/subgraph/tests/dao/dao_v1_3_0.test.ts +++ b/packages/subgraph/tests/dao/dao_v1_3_0.test.ts @@ -6,17 +6,18 @@ import { import {Executed} from '../../generated/templates/DaoTemplateV1_3_0/DAO'; import {handleExecuted} from '../../src/dao/dao_v1_3_0'; import {GOVERNANCE_WRAPPED_ERC20_INTERFACE_ID} from '../../src/utils/constants'; +import { + generateERC1155TransferEntityId, + generateTokenEntityId, +} from '../../src/utils/ids'; import { ERC20_transfer, - getTransferId, ERC20_transferFrom, ERC721_transferFrom, ERC721_safeTransferFromWithData, ERC1155_safeTransferFrom, ERC1155_safeBatchTransferFrom, ERC1155_INTERFACE_ID, - getTokenIdBalanceId, - getERC1155TransferId, ERC165_INTERFACE_ID, } from '../../src/utils/tokens/common'; import { @@ -45,6 +46,15 @@ import { getBalanceOf, getSupportsInterface, } from './utils'; +import { + generateActionEntityId, + generateBalanceEntityId, + generateDaoEntityId, + generateProposalEntityId, + generateTokenIdBalanceEntityId, + generateTransactionActionsProposalEntityId, + generateTransferEntityId, +} from '@aragon/osx-commons-subgraph'; import {ethereum, Bytes, Address, BigInt} from '@graphprotocol/graph-ts'; import { describe, @@ -57,9 +67,11 @@ import { } from 'matchstick-as'; const eq = assert.fieldEquals; -let daoId = Address.fromString(DAO_ADDRESS).toHexString(); -let tokenId = Address.fromString(DAO_TOKEN_ADDRESS).toHexString(); -let balanceId = daoId.concat('_').concat(tokenId); +let daoAddress = Address.fromString(DAO_ADDRESS); +let tokenAddress = Address.fromString(DAO_TOKEN_ADDRESS); +let daoEntityId = generateDaoEntityId(daoAddress); +let tokenEntityId = generateTokenEntityId(tokenAddress); +let balanceEntityId = generateBalanceEntityId(daoAddress, tokenAddress); describe('handleExecuted', () => { afterEach(() => { @@ -89,37 +101,57 @@ describe('handleExecuted', () => { handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); assert.entityCount('TransactionActionsProposal', 1); assert.entityCount('Action', 2); - eq('TransactionActionsProposal', proposalId, 'id', proposalId); - eq('TransactionActionsProposal', proposalId, 'failureMap', failureMap); eq( 'TransactionActionsProposal', - proposalId, + transactionActionsProposalEntityId, + 'id', + transactionActionsProposalEntityId + ); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, + 'failureMap', + failureMap + ); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, 'allowFailureMap', allowFailureMap ); for (let i = 0; i < event.params.actions.length; i++) { - let actionId = proposalId.concat('_').concat(i.toString()); + let actionEntityId = generateActionEntityId( + transactionActionsProposalEntityId, + i + ); - eq('Action', actionId, 'id', actionId); - eq('Action', actionId, 'execResult', execResults[i].toHexString()); - eq('Action', actionId, 'dao', DAO_ADDRESS); - eq('Action', actionId, 'proposal', proposalId); + eq('Action', actionEntityId, 'id', actionEntityId); + eq('Action', actionEntityId, 'execResult', execResults[i].toHexString()); + eq('Action', actionEntityId, 'dao', DAO_ADDRESS); eq( 'Action', - actionId, + actionEntityId, + 'proposal', + transactionActionsProposalEntityId + ); + eq( + 'Action', + actionEntityId, 'data', encodeWithFunctionSelector(tuple, selector).toHexString() ); @@ -142,19 +174,26 @@ describe('handleExecuted', () => { failureMap ); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); - let actionId = proposalId.concat('_').concat('0'); + let actionEntityId = generateActionEntityId( + transactionActionsProposalEntityId, + 0 + ); // create proposal - let proposal = new TransactionActionsProposal(proposalId); + let proposal = new TransactionActionsProposal( + transactionActionsProposalEntityId + ); proposal.dao = event.address.toHexString(); proposal.createdAt = event.block.timestamp; proposal.endDate = event.block.timestamp; @@ -166,7 +205,7 @@ describe('handleExecuted', () => { proposal.save(); // create action - let action = new Action(actionId); + let action = new Action(actionEntityId); action.to = Address.fromString(DAO_TOKEN_ADDRESS); action.data = Bytes.fromHexString('0x'); action.value = BigInt.zero(); @@ -186,14 +225,24 @@ describe('handleExecuted', () => { assert.entityCount('Action', 1); assert.entityCount('TransactionActionsProposal', 1); - eq('Action', actionId, 'id', actionId); - eq('Action', actionId, 'execResult', execResult.toHexString()); + eq('Action', actionEntityId, 'id', actionEntityId); + eq('Action', actionEntityId, 'execResult', execResult.toHexString()); - eq('TransactionActionsProposal', proposalId, 'id', proposalId); - eq('TransactionActionsProposal', proposalId, 'failureMap', failureMap); eq( 'TransactionActionsProposal', - proposalId, + transactionActionsProposalEntityId, + 'id', + transactionActionsProposalEntityId + ); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, + 'failureMap', + failureMap + ); + eq( + 'TransactionActionsProposal', + transactionActionsProposalEntityId, 'allowFailureMap', allowFailureMap ); @@ -247,42 +296,54 @@ describe('handleExecuted', () => { handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); let txHash = event.transaction.hash; let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); // check ERC20Contract entity - eq('ERC20Contract', tokenId, 'id', tokenId); - eq('ERC20Contract', tokenId, 'name', 'name'); - eq('ERC20Contract', tokenId, 'symbol', 'symbol'); + eq('ERC20Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC20Contract', tokenEntityId, 'name', 'name'); + eq('ERC20Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC20Contract', 1); // check ERC20Balance entity - eq('ERC20Balance', balanceId, 'id', balanceId); - eq('ERC20Balance', balanceId, 'token', tokenId); - eq('ERC20Balance', balanceId, 'dao', daoId); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); - eq('ERC20Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC20Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC20Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC20Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); + eq( + 'ERC20Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC20Balance', 1); // Check ERC20Transfer eq('ERC20Transfer', transferId, 'id', transferId); - eq('ERC20Transfer', transferId, 'dao', daoId); + eq('ERC20Transfer', transferId, 'dao', daoEntityId); eq('ERC20Transfer', transferId, 'amount', transferToken.toString()); eq('ERC20Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC20Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC20Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC20Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC20Transfer', transferId, 'type', 'Withdraw'); eq('ERC20Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC20Transfer', transferId, 'createdAt', timestamp.toString()); @@ -310,7 +371,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Transfer', 1); assert.entityCount('ERC20Balance', 1); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); // Mock balance of with different amount getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_FULL); @@ -324,7 +385,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Transfer', 2); assert.entityCount('ERC20Balance', 1); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_FULL); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_FULL); // Mock balance to get it back to the same before running this test getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_HALF); @@ -351,42 +412,54 @@ describe('handleExecuted', () => { handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); let txHash = event.transaction.hash; let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); // check ERC20Contract entity - eq('ERC20Contract', tokenId, 'id', tokenId); - eq('ERC20Contract', tokenId, 'name', 'name'); - eq('ERC20Contract', tokenId, 'symbol', 'symbol'); + eq('ERC20Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC20Contract', tokenEntityId, 'name', 'name'); + eq('ERC20Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC20Contract', 1); // check ERC20Balance entity - eq('ERC20Balance', balanceId, 'id', balanceId); - eq('ERC20Balance', balanceId, 'token', tokenId); - eq('ERC20Balance', balanceId, 'dao', daoId); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); - eq('ERC20Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC20Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC20Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC20Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); + eq( + 'ERC20Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC20Balance', 1); // Check ERC20Transfer eq('ERC20Transfer', transferId, 'id', transferId); - eq('ERC20Transfer', transferId, 'dao', daoId); + eq('ERC20Transfer', transferId, 'dao', daoEntityId); eq('ERC20Transfer', transferId, 'amount', transferToken.toString()); eq('ERC20Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC20Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC20Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC20Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC20Transfer', transferId, 'type', 'Withdraw'); eq('ERC20Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC20Transfer', transferId, 'createdAt', timestamp.toString()); @@ -414,7 +487,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Balance', 1); assert.entityCount('ERC20Transfer', 1); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_HALF); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_HALF); // Mock balance of with different amount getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_FULL); @@ -427,7 +500,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC20Contract', 1); assert.entityCount('ERC20Balance', 1); assert.entityCount('ERC20Transfer', 2); - eq('ERC20Balance', balanceId, 'balance', ERC20_AMOUNT_FULL); + eq('ERC20Balance', balanceEntityId, 'balance', ERC20_AMOUNT_FULL); // Mock balance to get it back to the same before running this test getBalanceOf(DAO_TOKEN_ADDRESS, DAO_ADDRESS, ERC20_AMOUNT_HALF); @@ -445,15 +518,15 @@ describe('handleExecuted', () => { }); beforeEach(() => { - let entity = new ERC721Balance(balanceId); - entity.dao = daoId; + let entity = new ERC721Balance(balanceEntityId); + entity.dao = daoEntityId; entity.tokenIds = [ BigInt.fromI32(4), BigInt.fromI32(8), BigInt.fromI32(12), ]; entity.lastUpdated = BigInt.fromI32(2); - entity.token = tokenId; + entity.token = tokenEntityId; entity.save(); }); @@ -480,40 +553,52 @@ describe('handleExecuted', () => { let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); // check ERC721Contract entity - eq('ERC721Contract', tokenId, 'id', tokenId); - eq('ERC721Contract', tokenId, 'name', 'name'); - eq('ERC721Contract', tokenId, 'symbol', 'symbol'); + eq('ERC721Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC721Contract', tokenEntityId, 'name', 'name'); + eq('ERC721Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC721Contract', 1); // check ERC721Balance entity - eq('ERC721Balance', balanceId, 'id', balanceId); - eq('ERC721Balance', balanceId, 'token', tokenId); - eq('ERC721Balance', balanceId, 'dao', daoId); - eq('ERC721Balance', balanceId, 'tokenIds', '[4, 12]'); - eq('ERC721Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC721Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC721Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC721Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4, 12]'); + eq( + 'ERC721Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC721Balance', 1); // Check ERC721Transfer eq('ERC721Transfer', transferId, 'id', transferId); - eq('ERC721Transfer', transferId, 'dao', daoId); + eq('ERC721Transfer', transferId, 'dao', daoEntityId); eq('ERC721Transfer', transferId, 'tokenId', transferToKen.toString()); eq('ERC721Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC721Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC721Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC721Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC721Transfer', transferId, 'type', 'Withdraw'); eq('ERC721Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC721Transfer', transferId, 'createdAt', timestamp.toString()); @@ -547,7 +632,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC721Contract', 1); assert.entityCount('ERC721Balance', 1); assert.entityCount('ERC721Transfer', 2); - eq('ERC721Balance', balanceId, 'tokenIds', '[4]'); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4]'); }); }); @@ -575,40 +660,52 @@ describe('handleExecuted', () => { let logIndex = event.transactionLogIndex; let timestamp = event.block.timestamp; - let transferId = getTransferId(txHash, logIndex, 0); + let transferId = generateTransferEntityId(txHash, logIndex, 0); handleExecuted(event); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(event.transaction.hash.toHexString()) - .concat('_') - .concat(event.transactionLogIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); // check ERC721Contract entity - eq('ERC721Contract', tokenId, 'id', tokenId); - eq('ERC721Contract', tokenId, 'name', 'name'); - eq('ERC721Contract', tokenId, 'symbol', 'symbol'); + eq('ERC721Contract', tokenEntityId, 'id', tokenEntityId); + eq('ERC721Contract', tokenEntityId, 'name', 'name'); + eq('ERC721Contract', tokenEntityId, 'symbol', 'symbol'); assert.entityCount('ERC721Contract', 1); // check ERC721Balance entity - eq('ERC721Balance', balanceId, 'id', balanceId); - eq('ERC721Balance', balanceId, 'token', tokenId); - eq('ERC721Balance', balanceId, 'dao', daoId); - eq('ERC721Balance', balanceId, 'tokenIds', '[4, 12]'); - eq('ERC721Balance', balanceId, 'lastUpdated', timestamp.toString()); + eq('ERC721Balance', balanceEntityId, 'id', balanceEntityId); + eq('ERC721Balance', balanceEntityId, 'token', tokenEntityId); + eq('ERC721Balance', balanceEntityId, 'dao', daoEntityId); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4, 12]'); + eq( + 'ERC721Balance', + balanceEntityId, + 'lastUpdated', + timestamp.toString() + ); assert.entityCount('ERC721Balance', 1); // Check ERC721Transfer eq('ERC721Transfer', transferId, 'id', transferId); - eq('ERC721Transfer', transferId, 'dao', daoId); + eq('ERC721Transfer', transferId, 'dao', daoEntityId); eq('ERC721Transfer', transferId, 'tokenId', transferToKen.toString()); eq('ERC721Transfer', transferId, 'from', DAO_ADDRESS); eq('ERC721Transfer', transferId, 'to', ADDRESS_THREE); - eq('ERC721Transfer', transferId, 'proposal', proposalId); + eq( + 'ERC721Transfer', + transferId, + 'proposal', + transactionActionsProposalEntityId + ); eq('ERC721Transfer', transferId, 'type', 'Withdraw'); eq('ERC721Transfer', transferId, 'txHash', txHash.toHexString()); eq('ERC721Transfer', transferId, 'createdAt', timestamp.toString()); @@ -644,7 +741,7 @@ describe('handleExecuted', () => { assert.entityCount('ERC721Contract', 1); assert.entityCount('ERC721Balance', 1); assert.entityCount('ERC721Transfer', 2); - eq('ERC721Balance', balanceId, 'tokenIds', '[4]'); + eq('ERC721Balance', balanceEntityId, 'tokenIds', '[4]'); }); }); }); @@ -718,22 +815,29 @@ describe('handleExecuted', () => { // check ERC1155Transfer entity let txHash = event.transaction.hash; let logIndex = event.transactionLogIndex; - let transferId = getERC1155TransferId(txHash, logIndex, 0, 0); - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(txHash.toHexString()) - .concat('_') - .concat(logIndex.toHexString()); + let transferId = generateERC1155TransferEntityId( + txHash, + logIndex, + 0, + 0 + ); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); assert.entityCount('ERC1155Transfer', 1); let erc1155Transfer = new ExtendedERC1155Transfer().withDefaultValues(); erc1155Transfer.id = transferId; erc1155Transfer.amount = amount; - erc1155Transfer.from = Address.fromHexString(daoId); + erc1155Transfer.from = Address.fromHexString(daoEntityId); erc1155Transfer.to = Address.fromHexString(ADDRESS_THREE); - erc1155Transfer.proposal = proposalId; + erc1155Transfer.proposal = transactionActionsProposalEntityId; erc1155Transfer.type = 'Withdraw'; erc1155Transfer.txHash = txHash; erc1155Transfer.createdAt = timestamp; @@ -766,7 +870,11 @@ describe('handleExecuted', () => { let erc1155TokenIdBalanceIdArray: string[] = []; for (let i = 0; i < transferTokens.length; i++) { erc1155TokenIdBalanceIdArray.push( - balanceId.concat('_').concat(transferTokens[i].toString()) + generateTokenIdBalanceEntityId( + daoAddress, + tokenAddress, + transferTokens[i] + ) ); } @@ -810,7 +918,11 @@ describe('handleExecuted', () => { // iterate over tokenIds for (let i = 0; i < tokenIds.length; i++) { tokenIdBalanceIdArray.push( - balanceId.concat('_').concat(tokenIds[i].toString()) + generateTokenIdBalanceEntityId( + daoAddress, + tokenAddress, + tokenIds[i] + ) ); } // check ERC1155Contract entity @@ -831,30 +943,37 @@ describe('handleExecuted', () => { erc1155TokenIdBalance.tokenId = tokenIds[i]; erc1155TokenIdBalance.amount = amounts[i]; erc1155TokenIdBalance.lastUpdated = timestamp; - erc1155TokenIdBalance.balance = balanceId; + erc1155TokenIdBalance.balance = balanceEntityId; erc1155TokenIdBalance.assertEntity(); } // check ERC1155Transfer entity let txHash = event.transaction.hash; let logIndex = event.transactionLogIndex; - let proposalId = event.params.actor - .toHexString() - .concat('_') - .concat(event.params.callId.toHexString()) - .concat('_') - .concat(txHash.toHexString()) - .concat('_') - .concat(logIndex.toHexString()); + let proposalEntityId = generateProposalEntityId( + event.params.actor, + BigInt.fromUnsignedBytes(event.params.callId) + ); + let transactionActionsProposalEntityId = + generateTransactionActionsProposalEntityId( + proposalEntityId, + event.transaction.hash, + event.transactionLogIndex + ); for (let i = 0; i < tokenIds.length; i++) { let erc1155Transfer = new ExtendedERC1155Transfer().withDefaultValues(); - erc1155Transfer.id = getERC1155TransferId(txHash, logIndex, 0, i); + erc1155Transfer.id = generateERC1155TransferEntityId( + txHash, + logIndex, + 0, + i + ); // appeend index to transferId to make sure it is unique erc1155Transfer.amount = amounts[i]; - erc1155Transfer.from = Address.fromHexString(daoId); + erc1155Transfer.from = Address.fromHexString(daoEntityId); erc1155Transfer.to = Address.fromHexString(ADDRESS_THREE); erc1155Transfer.tokenId = tokenIds[i]; - erc1155Transfer.proposal = proposalId; + erc1155Transfer.proposal = transactionActionsProposalEntityId; erc1155Transfer.type = 'Withdraw'; erc1155Transfer.txHash = txHash; erc1155Transfer.createdAt = timestamp; @@ -892,7 +1011,11 @@ describe('handleExecuted', () => { let erc1155TokenIdBalanceIdArray: string[] = []; for (let i = 0; i < tokenIds[0].length; i++) { erc1155TokenIdBalanceIdArray.push( - getTokenIdBalanceId(daoId, tokenId, tokenIds[0][i]) + generateTokenIdBalanceEntityId( + daoAddress, + tokenAddress, + tokenIds[0][i] + ) ); } // check ERC ontract entity diff --git a/packages/subgraph/tests/helpers/method-classes.ts b/packages/subgraph/tests/helpers/method-classes.ts index b8fa71ffd..95e400602 100644 --- a/packages/subgraph/tests/helpers/method-classes.ts +++ b/packages/subgraph/tests/helpers/method-classes.ts @@ -47,6 +47,7 @@ import { VOTING_MODES, VOTING_MODE_INDEXES, } from '../../src/utils/constants'; +import {generateMemberEntityId} from '../../src/utils/ids'; import { getBalanceId, getERC1155TransferId, @@ -90,7 +91,7 @@ import { import { createNewGrantedEvent, createNewRevokedEvent, -} from '../permission-mamager/utils'; +} from '../permission-manager/utils'; import { createNewDelegateChangedEvent, createNewDelegateVotesChangedEvent, @@ -109,6 +110,11 @@ import { createWrappedTokenCalls, createERC1155TokenCalls, } from '../utils'; +import { + generateEntityIdFromAddress, + generatePermissionEntityId, + generatePluginEntityId, +} from '@aragon/osx-commons-subgraph'; import { Address, BigInt, @@ -130,22 +136,23 @@ class PermissionMethods extends Permission { crypto.keccak256(ByteArray.fromUTF8('EXECUTE_PERMISSION')) ); - const where = Address.fromString(ADDRESS_ONE); - const who = Address.fromString(ADDRESS_TWO); - const actor = Address.fromString(ADDRESS_THREE); - const condition = Address.fromString(ADDRESS_FOUR); - - this.id = [ - emittingContract, - permissionId.toHexString(), - where.toHexString(), - who.toHexString(), - ].join('_'); - this.where = where; + const emittingContractAddress = Address.fromString(emittingContract); + const whereAddress = Address.fromString(ADDRESS_ONE); + const whoAddress = Address.fromString(ADDRESS_TWO); + const actorAddress = Address.fromString(ADDRESS_THREE); + const conditionAddress = Address.fromString(ADDRESS_FOUR); + + this.id = generatePermissionEntityId( + emittingContractAddress, + permissionId, + whereAddress, + whoAddress + ); + this.where = whereAddress; this.permissionId = permissionId; - this.who = who; - this.actor = actor; - this.condition = condition; + this.who = whoAddress; + this.actor = actorAddress; + this.condition = conditionAddress; this.dao = null; this.pluginRepo = null; @@ -536,12 +543,13 @@ class DaoMethods extends Dao { // Token Voting class TokenVotingVoterMethods extends TokenVotingVoter { withDefaultValues(): TokenVotingVoterMethods { - this.id = Address.fromHexString(CONTRACT_ADDRESS) - .toHexString() - .concat('_') - .concat(ADDRESS_ONE); - this.address = ADDRESS_ONE; - this.plugin = Address.fromHexString(CONTRACT_ADDRESS).toHexString(); + const memberAddress = Address.fromString(ADDRESS_ONE); + const memberId = generateEntityIdFromAddress(memberAddress); + const pluginAddress = Address.fromString(CONTRACT_ADDRESS); + const pluginEntityId = generatePluginEntityId(pluginAddress); + this.id = generateMemberEntityId(pluginAddress, memberAddress); + this.address = memberId; + this.plugin = pluginEntityId; this.lastUpdated = BigInt.zero(); return this; @@ -708,10 +716,10 @@ class TokenVotingPluginMethods extends TokenVotingPlugin { // we use casting here to remove autocompletion complaint // since we know it will be captured by the previous check let votingMode = VOTING_MODES.get(votingModeIndex) as string; + const pluginAddress = Address.fromString(CONTRACT_ADDRESS); + const pluginEntityId = generatePluginEntityId(pluginAddress); - const pluginAddress = Address.fromHexString(CONTRACT_ADDRESS); - - this.id = pluginAddress.toHexString(); + this.id = pluginEntityId; this.dao = DAO_ADDRESS; this.pluginAddress = pluginAddress; this.votingMode = votingMode; diff --git a/packages/subgraph/tests/multisig/multisig.test.ts b/packages/subgraph/tests/multisig/multisig.test.ts index a94c3247c..f19f3da41 100644 --- a/packages/subgraph/tests/multisig/multisig.test.ts +++ b/packages/subgraph/tests/multisig/multisig.test.ts @@ -7,7 +7,10 @@ import { _handleProposalCreated, handleMultisigSettingsUpdated, } from '../../src/packages/multisig/multisig'; -import {getProposalId} from '../../src/utils/proposals'; +import { + generateMemberEntityId, + generateVoterEntityId, +} from '../../src/utils/ids'; import { ADDRESS_ONE, ADDRESS_TWO, @@ -37,11 +40,21 @@ import { createNewMultisigSettingsUpdatedEvent, createMultisigPluginState, } from './utils'; +import { + generatePluginEntityId, + generateProposalEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as/assembly/index'; let actions = createDummyActions(DAO_TOKEN_ADDRESS, '0', '0x00000000'); +const pluginAddress = Address.fromString(CONTRACT_ADDRESS); +const pluginEntityId = generatePluginEntityId(pluginAddress); +const daoAddress = Address.fromString(DAO_ADDRESS); +const daoEntityId = generatePluginEntityId(daoAddress); +const pluginProposalId = BigInt.fromString(PLUGIN_PROPOSAL_ID); + test('Run Multisig (handleProposalCreated) mappings with mock event', () => { // create state createMultisigPluginState(); @@ -82,51 +95,74 @@ test('Run Multisig (handleProposalCreated) mappings with mock event', () => { // handle event _handleProposalCreated(event, DAO_ADDRESS, STRING_DATA); - let entityID = getProposalId( - Address.fromString(CONTRACT_ADDRESS), - BigInt.fromString(PLUGIN_PROPOSAL_ID) + let proposalEntityId = generateProposalEntityId( + pluginAddress, + pluginProposalId ); - let packageId = Address.fromString(CONTRACT_ADDRESS).toHexString(); - // checks - assert.fieldEquals('MultisigProposal', entityID, 'id', entityID); - assert.fieldEquals('MultisigProposal', entityID, 'dao', DAO_ADDRESS); - assert.fieldEquals('MultisigProposal', entityID, 'plugin', packageId); assert.fieldEquals( 'MultisigProposal', - entityID, + proposalEntityId, + 'id', + proposalEntityId + ); + assert.fieldEquals('MultisigProposal', proposalEntityId, 'dao', DAO_ADDRESS); + assert.fieldEquals( + 'MultisigProposal', + proposalEntityId, + 'plugin', + pluginEntityId + ); + assert.fieldEquals( + 'MultisigProposal', + proposalEntityId, 'pluginProposalId', PLUGIN_PROPOSAL_ID ); - assert.fieldEquals('MultisigProposal', entityID, 'creator', ADDRESS_ONE); - assert.fieldEquals('MultisigProposal', entityID, 'startDate', START_DATE); - assert.fieldEquals('MultisigProposal', entityID, 'endDate', END_DATE); - assert.fieldEquals('MultisigProposal', entityID, 'metadata', STRING_DATA); assert.fieldEquals( 'MultisigProposal', - entityID, + proposalEntityId, + 'creator', + ADDRESS_ONE + ); + assert.fieldEquals( + 'MultisigProposal', + proposalEntityId, + 'startDate', + START_DATE + ); + assert.fieldEquals('MultisigProposal', proposalEntityId, 'endDate', END_DATE); + assert.fieldEquals( + 'MultisigProposal', + proposalEntityId, + 'metadata', + STRING_DATA + ); + assert.fieldEquals( + 'MultisigProposal', + proposalEntityId, 'createdAt', event.block.timestamp.toString() ); assert.fieldEquals( 'MultisigProposal', - entityID, + proposalEntityId, 'creationBlockNumber', event.block.number.toString() ); assert.fieldEquals( 'MultisigProposal', - entityID, + proposalEntityId, 'snapshotBlock', SNAPSHOT_BLOCK ); - assert.fieldEquals('MultisigProposal', entityID, 'minApprovals', ONE); - assert.fieldEquals('MultisigProposal', entityID, 'approvals', ONE); - assert.fieldEquals('MultisigProposal', entityID, 'executed', 'false'); + assert.fieldEquals('MultisigProposal', proposalEntityId, 'minApprovals', ONE); + assert.fieldEquals('MultisigProposal', proposalEntityId, 'approvals', ONE); + assert.fieldEquals('MultisigProposal', proposalEntityId, 'executed', 'false'); assert.fieldEquals( 'MultisigProposal', - entityID, + proposalEntityId, 'allowFailureMap', ALLOW_FAILURE_MAP ); @@ -180,33 +216,33 @@ test('Run Multisig (handleApproved) mappings with mock event', () => { handleApproved(event); // checks - const member = Address.fromString(ADDRESS_ONE).toHexString(); - const pluginId = Address.fromString(CONTRACT_ADDRESS).toHexString(); - const memberId = pluginId + '_' + member; + const memberAddress = Address.fromString(ADDRESS_ONE); + + const memberEntityId = generateMemberEntityId(pluginAddress, memberAddress); + const voterEntityId = generateVoterEntityId(memberEntityId, proposal.id); // check proposalVoter - let proposalVoterId = member + '_' + proposal.id; assert.fieldEquals( 'MultisigProposalApprover', - proposalVoterId, + voterEntityId, 'id', - proposalVoterId + voterEntityId ); assert.fieldEquals( 'MultisigProposalApprover', - proposalVoterId, + voterEntityId, 'approver', - memberId + memberEntityId ); assert.fieldEquals( 'MultisigProposalApprover', - proposalVoterId, + voterEntityId, 'proposal', proposal.id ); assert.fieldEquals( 'MultisigProposalApprover', - proposalVoterId, + voterEntityId, 'createdAt', event.block.timestamp.toString() ); diff --git a/packages/subgraph/tests/permission-mamager/permission-manager.test.ts b/packages/subgraph/tests/permission-manager/permission-manager.test.ts similarity index 66% rename from packages/subgraph/tests/permission-mamager/permission-manager.test.ts rename to packages/subgraph/tests/permission-manager/permission-manager.test.ts index 985716837..e8e1ddc71 100644 --- a/packages/subgraph/tests/permission-mamager/permission-manager.test.ts +++ b/packages/subgraph/tests/permission-manager/permission-manager.test.ts @@ -16,18 +16,22 @@ import { } from '../../src/plugin/pluginRepo'; import {CONTRACT_ADDRESS, DAO_ADDRESS} from '../constants'; import {ExtendedPermission} from '../helpers/extended-schema'; +import {generateDaoEntityId} from '@aragon/osx-commons-subgraph'; import {Address} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as/assembly/index'; -const daoId = Address.fromString(DAO_ADDRESS).toHexString(); -const pluginRepoId = Address.fromString(CONTRACT_ADDRESS).toHexString(); +const daoAddress = Address.fromString(DAO_ADDRESS); +const pluginRepoAddress = Address.fromString(CONTRACT_ADDRESS); +const daoEntityId = generateDaoEntityId(daoAddress); +const pluginRepoEntityId = generateDaoEntityId(pluginRepoAddress); // DAO test('Run dao (handleGranted) mappings with mock event', () => { - let permission = new ExtendedPermission().withDefaultValues(daoId); - permission.dao = daoId; + let permission = new ExtendedPermission().withDefaultValues(daoEntityId); + permission.dao = daoEntityId; - let grantedEvent = permission.createEvent_Granted(daoId); + let grantedEvent = + permission.createEvent_Granted(daoEntityId); // handle event daoHandleGranted(grantedEvent); @@ -39,8 +43,8 @@ test('Run dao (handleGranted) mappings with mock event', () => { }); test('Run dao (handleRevoked) mappings with mock event', () => { - let permission = new ExtendedPermission().withDefaultValues(daoId); - permission.dao = daoId; + let permission = new ExtendedPermission().withDefaultValues(daoEntityId); + permission.dao = daoEntityId; permission.save(); @@ -48,7 +52,8 @@ test('Run dao (handleRevoked) mappings with mock event', () => { permission.assertEntity(); // create event and run it's handler - let revokedEvent = permission.createEvent_Revoked(daoId); + let revokedEvent = + permission.createEvent_Revoked(daoEntityId); // handle event daoHandleRevoked(revokedEvent); @@ -61,11 +66,13 @@ test('Run dao (handleRevoked) mappings with mock event', () => { // PluginRepo test('Run PluginRepo (handleGranted) mappings with mock event', () => { - let permission = new ExtendedPermission().withDefaultValues(pluginRepoId); - permission.pluginRepo = pluginRepoId; + let permission = new ExtendedPermission().withDefaultValues( + pluginRepoEntityId + ); + permission.pluginRepo = pluginRepoEntityId; let grantedEvent = - permission.createEvent_Granted(pluginRepoId); + permission.createEvent_Granted(pluginRepoEntityId); // handle event repoHandleGranted(grantedEvent); @@ -77,8 +84,10 @@ test('Run PluginRepo (handleGranted) mappings with mock event', () => { }); test('Run PluginRepo (handleRevoked) mappings with mock event', () => { - let permission = new ExtendedPermission().withDefaultValues(pluginRepoId); - permission.pluginRepo = pluginRepoId; + let permission = new ExtendedPermission().withDefaultValues( + pluginRepoEntityId + ); + permission.pluginRepo = pluginRepoEntityId; permission.save(); @@ -87,7 +96,7 @@ test('Run PluginRepo (handleRevoked) mappings with mock event', () => { // create event and run it's handler let revokedEvent = - permission.createEvent_Revoked(pluginRepoId); + permission.createEvent_Revoked(pluginRepoEntityId); // handle event repoHandleRevoked(revokedEvent); diff --git a/packages/subgraph/tests/permission-mamager/utils.ts b/packages/subgraph/tests/permission-manager/utils.ts similarity index 100% rename from packages/subgraph/tests/permission-mamager/utils.ts rename to packages/subgraph/tests/permission-manager/utils.ts diff --git a/packages/subgraph/tests/plugin/pluginRepo.test.ts b/packages/subgraph/tests/plugin/pluginRepo.test.ts index fb9331634..25f82eb7d 100644 --- a/packages/subgraph/tests/plugin/pluginRepo.test.ts +++ b/packages/subgraph/tests/plugin/pluginRepo.test.ts @@ -4,6 +4,11 @@ import { } from '../../src/plugin/pluginRepo'; import {ADDRESS_ONE, ONE} from '../constants'; import {createReleaseMetadataUpdatedEvent, createVersionCreated} from './utils'; +import { + generatePluginReleaseEntityId, + generatePluginRepoEntityId, + generatePluginVersionEntityId, +} from '@aragon/osx-commons-subgraph'; import {Bytes} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as/assembly/index'; @@ -22,40 +27,46 @@ test('PluginRepo (handleVersionCreated) mappings with mock event', () => { handleVersionCreated(event); - let pluginRepoId = event.address.toHexString(); - - let pluginVersionId = pluginRepoId - .concat('_') - .concat(release) - .concat('_') - .concat(build); + let pluginVersionEntityId = generatePluginVersionEntityId( + event.address, + parseInt(release) as i32, + parseInt(build) as i32 + ); - let pluginReleaseId = pluginRepoId.concat('_').concat(release); + let pluginReleaseEntityId = generatePluginReleaseEntityId( + event.address, + parseInt(release) as i32 + ); assert.entityCount('PluginVersion', 1); - assert.fieldEquals('PluginVersion', pluginVersionId, 'id', pluginVersionId); assert.fieldEquals( 'PluginVersion', - pluginVersionId, + pluginVersionEntityId, + 'id', + pluginVersionEntityId + ); + assert.fieldEquals( + 'PluginVersion', + pluginVersionEntityId, 'pluginRepo', event.address.toHexString() ); assert.fieldEquals( 'PluginVersion', - pluginVersionId, + pluginVersionEntityId, 'release', - pluginReleaseId + pluginReleaseEntityId ); - assert.fieldEquals('PluginVersion', pluginVersionId, 'build', build); + assert.fieldEquals('PluginVersion', pluginVersionEntityId, 'build', build); assert.fieldEquals( 'PluginVersion', - pluginVersionId, + pluginVersionEntityId, 'pluginSetup', pluginSetup ); assert.fieldEquals( 'PluginVersion', - pluginVersionId, + pluginVersionEntityId, 'metadata', buildMetadata ); @@ -79,8 +90,11 @@ test('PluginRepo (handleReleaseMetadataUpdated) mappings with mock event', () => assert.entityCount('PluginRelease', 1); - let pluginRepoId = event.address.toHexString(); - let pluginReleaseEntityId = pluginRepoId.concat('_').concat(release); + let pluginRepoEntityId = generatePluginRepoEntityId(event.address); + let pluginReleaseEntityId = generatePluginReleaseEntityId( + event.address, + parseInt(release) as i32 + ); assert.fieldEquals( 'PluginRelease', @@ -92,7 +106,7 @@ test('PluginRepo (handleReleaseMetadataUpdated) mappings with mock event', () => 'PluginRelease', pluginReleaseEntityId, 'pluginRepo', - pluginRepoId + pluginRepoEntityId ); assert.fieldEquals( 'PluginRelease', diff --git a/packages/subgraph/tests/plugin/pluginSetupProcessor.test.ts b/packages/subgraph/tests/plugin/pluginSetupProcessor.test.ts index 5e4d8803d..4aa23d7b5 100644 --- a/packages/subgraph/tests/plugin/pluginSetupProcessor.test.ts +++ b/packages/subgraph/tests/plugin/pluginSetupProcessor.test.ts @@ -1,4 +1,7 @@ -import {PluginPreparation} from '../../generated/schema'; +import { + PluginInstallationLoader, + PluginPreparation, +} from '../../generated/schema'; import { handleInstallationApplied, handleInstallationPrepared, @@ -39,22 +42,41 @@ import { createUpdateAppliedEvent, createUpdatePreparedEvent, } from './utils'; +import { + generateDaoEntityId, + generatePermissionEntityId, + generatePluginEntityId, + generatePluginInstallationEntityId, + generatePluginPermissionEntityId, + generatePluginPreparationEntityId, + generatePluginRepoEntityId, + generatePluginVersionEntityId, +} from '@aragon/osx-commons-subgraph'; import {Address, BigInt, Bytes, ethereum} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as'; +const daoAddress = Address.fromString(DAO_ADDRESS); +const daoEntityId = generateDaoEntityId(daoAddress); +const pluginAddress = Address.fromString(CONTRACT_ADDRESS); +const pluginEntityId = generatePluginEntityId(pluginAddress); +const setupId = PLUGIN_SETUP_ID; +const pluginRepoAddress = Address.fromString(ADDRESS_TWO); +const pluginRepoEntityId = generatePluginRepoEntityId(pluginRepoAddress); + test('InstallationPrepared event', function () { - let dao = DAO_ADDRESS; - let plugin = CONTRACT_ADDRESS; - let setupId = PLUGIN_SETUP_ID; - let pluginSetupRepo = ADDRESS_TWO; - let pluginVersionId = `${pluginSetupRepo}_1_1`; - let installationId = getPluginInstallationId(dao, plugin); - if (!installationId) { + let pluginVersionId = generatePluginVersionEntityId(pluginRepoAddress, 1, 1); + let pluginInstallationEntityId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); + if (!pluginInstallationEntityId) { throw new Error('Failed to get installationId'); } - - let installationIdString = installationId.toHexString(); - let preparationId = `${installationIdString}_${setupId}`; + pluginInstallationEntityId = pluginInstallationEntityId as string; + let pluginPreparationEntityId = generatePluginPreparationEntityId( + pluginInstallationEntityId, + Bytes.fromHexString(setupId) + ); let versionTuple = new ethereum.Tuple(); versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromString('1'))); @@ -63,32 +85,32 @@ test('InstallationPrepared event', function () { let permissions = [ [ ethereum.Value.fromSignedBigInt(BigInt.fromString('0')), - ethereum.Value.fromAddress(Address.fromString(dao)), - ethereum.Value.fromAddress(Address.fromString(plugin)), + ethereum.Value.fromAddress(daoAddress), + ethereum.Value.fromAddress(pluginAddress), ethereum.Value.fromAddress(Address.fromString(ADDRESS_ZERO)), ethereum.Value.fromBytes(Bytes.fromHexString('0x1234')), ], [ ethereum.Value.fromSignedBigInt(BigInt.fromString('2')), - ethereum.Value.fromAddress(Address.fromString(dao)), - ethereum.Value.fromAddress(Address.fromString(plugin)), + ethereum.Value.fromAddress(daoAddress), + ethereum.Value.fromAddress(pluginAddress), ethereum.Value.fromAddress(Address.fromString(ADDRESS_SIX)), ethereum.Value.fromBytes(Bytes.fromHexString('0x5678')), ], ]; - getSupportsInterface(plugin, TOKEN_VOTING_INTERFACE_ID, false); - getSupportsInterface(plugin, ADDRESSLIST_VOTING_INTERFACE_ID, false); - getSupportsInterface(plugin, ADMIN_INTERFACE_ID, false); - getSupportsInterface(plugin, MULTISIG_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, TOKEN_VOTING_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, ADDRESSLIST_VOTING_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, ADMIN_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, MULTISIG_INTERFACE_ID, false); let event = createInstallationPreparedEvent( ADDRESS_THREE, - dao, - plugin, + daoEntityId, + pluginEntityId, Bytes.fromHexString(setupId), - pluginSetupRepo, + pluginRepoEntityId, versionTuple, Bytes.fromHexString('0x00'), [ADDRESS_FOUR, ADDRESS_FIVE], @@ -98,53 +120,63 @@ test('InstallationPrepared event', function () { handleInstallationPrepared(event); assert.entityCount('PluginPreparation', 1); - assert.fieldEquals('PluginPreparation', preparationId, 'id', preparationId); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, + 'id', + pluginPreparationEntityId + ); + assert.fieldEquals( + 'PluginPreparation', + pluginPreparationEntityId, 'installation', - installationIdString + pluginInstallationEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'creator', ADDRESS_THREE ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'preparedSetupId', setupId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'pluginRepo', - pluginSetupRepo + pluginRepoEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'pluginVersion', pluginVersionId ); - assert.fieldEquals('PluginPreparation', preparationId, 'data', '0x00'); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, + 'data', + '0x00' + ); + assert.fieldEquals( + 'PluginPreparation', + pluginPreparationEntityId, 'pluginAddress', - plugin.toLowerCase() + pluginEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'type', 'Installation' ); @@ -153,9 +185,11 @@ test('InstallationPrepared event', function () { Address.fromString(ADDRESS_FOUR), Address.fromString(ADDRESS_FIVE), ]; - let pluginPreparation = PluginPreparation.load(preparationId); + let pluginPreparation = PluginPreparation.load(pluginPreparationEntityId); if (!pluginPreparation) { - throw new Error(`PluginPrepation with id ${preparationId} not found`); + throw new Error( + `PluginPrepation with id ${pluginPreparationEntityId} not found` + ); } assert.equals( @@ -166,45 +200,47 @@ test('InstallationPrepared event', function () { assert.entityCount('PluginPermission', permissions.length); for (let i = 0; i < permissions.length; i++) { let permission = permissions[i]; - let operation = PERMISSION_OPERATIONS.get(permission[0].toI32()); - let permissionEntityId = `${preparationId}_${operation}_${permission[1] - .toAddress() - .toHexString()}_${permission[2].toAddress().toHexString()}_${permission[4] - .toBytes() - .toHexString()}`; + let operation = permission[0].toI32(); + let pluginPermissionEntityId = generatePluginPermissionEntityId( + pluginPreparationEntityId, + operation, + permission[1].toAddress(), + permission[2].toAddress(), + permission[4].toBytes() + ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'id', - permissionEntityId + pluginPermissionEntityId ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'operation', - operation || '' + PERMISSION_OPERATIONS.get(operation) || '' ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'where', permission[1].toAddress().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'who', permission[2].toAddress().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'permissionId', permission[4].toBytes().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'condition', permission[3].toAddress().toHexString() ); @@ -213,13 +249,13 @@ test('InstallationPrepared event', function () { assert.entityCount('PluginInstallation', 1); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'state', 'InstallationPrepared' ); @@ -233,19 +269,22 @@ test('InstallationPrepared event', function () { }); test('InstallationApplied event', function () { - let dao = DAO_ADDRESS; - let plugin = ADDRESS_ONE; - let setupId = PLUGIN_SETUP_ID; - let installationId = getPluginInstallationId(dao, plugin); - if (!installationId) { + let pluginInstallationEntityId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); + if (!pluginInstallationEntityId) { throw new Error('Failed to get installationId'); } - let installationIdString = installationId.toHexString(); - let preparationId = `${installationIdString}_${setupId}`; + pluginInstallationEntityId = pluginInstallationEntityId as string; + let pluginPreparationEntityId = generatePluginPreparationEntityId( + pluginInstallationEntityId, + Bytes.fromHexString(setupId) + ); let event = createInstallationAppliedEvent( - dao, - plugin, + daoEntityId, + pluginEntityId, Bytes.fromHexString(setupId), Bytes.fromHexString(APPLIED_PLUGIN_SETUP_ID) ); @@ -254,37 +293,37 @@ test('InstallationApplied event', function () { assert.entityCount('PluginInstallation', 1); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'id', - installationIdString + pluginInstallationEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'plugin', - plugin.toLowerCase() + pluginEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'appliedPreparation', - preparationId + pluginPreparationEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'appliedSetupId', APPLIED_PLUGIN_SETUP_ID ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'state', 'Installed' ); @@ -293,35 +332,43 @@ test('InstallationApplied event', function () { }); test('UpdatePrepared event', function () { - let dao = DAO_ADDRESS; - let plugin = ADDRESS_ONE; - let setupId = PLUGIN_SETUP_ID; - let pluginSetupRepo = ADDRESS_TWO; - let pluginVersionId = `${pluginSetupRepo}_1_2`; - let installationId = getPluginInstallationId(dao, plugin); - if (!installationId) { + const build = 1; + const release = 2; + const pluginVersionEntityId = generatePluginVersionEntityId( + pluginRepoAddress, + build, + release + ); + let pluginInstallationEntityId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); + if (!pluginInstallationEntityId) { throw new Error('Failed to get installationId'); } - let installationIdString = installationId.toHexString(); - let preparationId = `${installationIdString}_${setupId}`; + pluginInstallationEntityId = pluginInstallationEntityId as string; + const pluginPreparationEntityId = generatePluginPreparationEntityId( + pluginInstallationEntityId, + Bytes.fromHexString(setupId) + ); let versionTuple = new ethereum.Tuple(); - versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromString('1'))); - versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromString('2'))); + versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromI32(build))); + versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromI32(release))); let permissions = [ [ ethereum.Value.fromSignedBigInt(BigInt.fromString('0')), - ethereum.Value.fromAddress(Address.fromString(dao)), - ethereum.Value.fromAddress(Address.fromString(plugin)), + ethereum.Value.fromAddress(daoAddress), + ethereum.Value.fromAddress(pluginAddress), ethereum.Value.fromAddress(Address.fromString(ADDRESS_ZERO)), ethereum.Value.fromBytes(Bytes.fromHexString('0x1234')), ], [ ethereum.Value.fromSignedBigInt(BigInt.fromString('2')), - ethereum.Value.fromAddress(Address.fromString(dao)), - ethereum.Value.fromAddress(Address.fromString(plugin)), + ethereum.Value.fromAddress(daoAddress), + ethereum.Value.fromAddress(pluginAddress), ethereum.Value.fromAddress(Address.fromString(ADDRESS_SIX)), ethereum.Value.fromBytes(Bytes.fromHexString('0x5678')), ], @@ -329,10 +376,10 @@ test('UpdatePrepared event', function () { let event = createUpdatePreparedEvent( ADDRESS_THREE, - dao, - plugin, + daoEntityId, + pluginEntityId, Bytes.fromHexString(setupId), - pluginSetupRepo, + pluginRepoEntityId, versionTuple, [], [ADDRESS_FOUR, ADDRESS_FIVE], @@ -343,53 +390,70 @@ test('UpdatePrepared event', function () { handleUpdatePrepared(event); assert.entityCount('PluginPreparation', 1); - assert.fieldEquals('PluginPreparation', preparationId, 'id', preparationId); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, + 'id', + pluginPreparationEntityId + ); + assert.fieldEquals( + 'PluginPreparation', + pluginPreparationEntityId, 'installation', - installationIdString + pluginInstallationEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'creator', ADDRESS_THREE ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'preparedSetupId', setupId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'pluginRepo', - pluginSetupRepo + pluginRepoEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'pluginVersion', - pluginVersionId + pluginVersionEntityId + ); + assert.fieldEquals( + 'PluginPreparation', + pluginPreparationEntityId, + 'data', + '0x12' + ); + assert.fieldEquals( + 'PluginPreparation', + pluginPreparationEntityId, + 'type', + 'Update' ); - assert.fieldEquals('PluginPreparation', preparationId, 'data', '0x12'); - assert.fieldEquals('PluginPreparation', preparationId, 'type', 'Update'); let helpers = [ Address.fromString(ADDRESS_FOUR), Address.fromString(ADDRESS_FIVE), ]; - let pluginPreparation = PluginPreparation.load(preparationId); + let pluginPreparation = PluginPreparation.load(pluginPreparationEntityId); if (!pluginPreparation) { - throw new Error(`PluginPrepation with id ${preparationId} not found`); + throw new Error( + `PluginPrepation with id ${pluginPreparationEntityId} not found` + ); } assert.equals( @@ -401,45 +465,47 @@ test('UpdatePrepared event', function () { for (let i = 0; i < permissions.length; i++) { let permission = permissions[i]; - let operation = PERMISSION_OPERATIONS.get(permission[0].toI32()); - let permissionEntityId = `${preparationId}_${operation}_${permission[1] - .toAddress() - .toHexString()}_${permission[2].toAddress().toHexString()}_${permission[4] - .toBytes() - .toHexString()}`; + let operation = permission[0].toI32(); + const pluginPermissionEntityId = generatePluginPermissionEntityId( + pluginPreparationEntityId, + operation, + permission[1].toAddress(), + permission[2].toAddress(), + permission[4].toBytes() + ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'id', - permissionEntityId + pluginPermissionEntityId ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'operation', - operation || '' + PERMISSION_OPERATIONS.get(operation) || '' ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'where', permission[1].toAddress().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'who', permission[2].toAddress().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'permissionId', permission[4].toBytes().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'condition', permission[3].toAddress().toHexString() ); @@ -448,13 +514,13 @@ test('UpdatePrepared event', function () { assert.entityCount('PluginInstallation', 1); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'state', 'UpdatePrepared' ); @@ -463,24 +529,27 @@ test('UpdatePrepared event', function () { }); test('UpdateApplied event', function () { - let dao = DAO_ADDRESS; - let plugin = ADDRESS_ONE; - let setupId = PLUGIN_SETUP_ID; - let installationId = getPluginInstallationId(dao, plugin); - if (!installationId) { + let pluginInstallationEntityId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); + if (!pluginInstallationEntityId) { throw new Error('Failed to get installationId'); } - let installationIdString = installationId.toHexString(); - let preparationId = `${installationIdString}_${setupId}`; + pluginInstallationEntityId = pluginInstallationEntityId as string; + const pluginPreparationEntityId = generatePluginPreparationEntityId( + pluginInstallationEntityId, + Bytes.fromHexString(setupId) + ); - getSupportsInterface(plugin, TOKEN_VOTING_INTERFACE_ID, false); - getSupportsInterface(plugin, ADDRESSLIST_VOTING_INTERFACE_ID, false); - getSupportsInterface(plugin, ADMIN_INTERFACE_ID, false); - getSupportsInterface(plugin, MULTISIG_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, TOKEN_VOTING_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, ADDRESSLIST_VOTING_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, ADMIN_INTERFACE_ID, false); + getSupportsInterface(pluginEntityId, MULTISIG_INTERFACE_ID, false); let event = createUpdateAppliedEvent( - dao, - plugin, + daoEntityId, + pluginEntityId, Bytes.fromHexString(setupId), Bytes.fromHexString(APPLIED_PLUGIN_SETUP_ID) ); @@ -489,37 +558,37 @@ test('UpdateApplied event', function () { assert.entityCount('PluginInstallation', 1); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'id', - installationIdString + pluginInstallationEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'plugin', - plugin.toLowerCase() + pluginEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'appliedPreparation', - preparationId + pluginPreparationEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'appliedSetupId', APPLIED_PLUGIN_SETUP_ID ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'state', 'Installed' ); @@ -528,35 +597,42 @@ test('UpdateApplied event', function () { }); test('UninstallationPrepared event', function () { - let dao = DAO_ADDRESS; - let plugin = ADDRESS_ONE; - let setupId = PLUGIN_SETUP_ID; - let pluginSetupRepo = ADDRESS_TWO; - let installationId = getPluginInstallationId(dao, plugin); - if (!installationId) { + let pluginInstallationEntityId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); + if (!pluginInstallationEntityId) { throw new Error('Failed to get installationId'); } - let installationIdString = installationId.toHexString(); - let preparationId = `${installationIdString}_${setupId}`; - - let pluginVersionId = `${pluginSetupRepo}_1_2`; + pluginInstallationEntityId = pluginInstallationEntityId as string; + const build = 1; + const release = 2; + const pluginPreparationEntityId = generatePluginPreparationEntityId( + pluginInstallationEntityId, + Bytes.fromHexString(setupId) + ); + const pluginVersionEntityId = generatePluginVersionEntityId( + pluginRepoAddress, + build, + release + ); let versionTuple = new ethereum.Tuple(); - versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromString('1'))); - versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromString('2'))); + versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromI32(build))); + versionTuple.push(ethereum.Value.fromSignedBigInt(BigInt.fromI32(release))); let permissions = [ [ ethereum.Value.fromSignedBigInt(BigInt.fromString('0')), - ethereum.Value.fromAddress(Address.fromString(dao)), - ethereum.Value.fromAddress(Address.fromString(plugin)), + ethereum.Value.fromAddress(daoAddress), + ethereum.Value.fromAddress(pluginAddress), ethereum.Value.fromAddress(Address.fromString(ADDRESS_ZERO)), ethereum.Value.fromBytes(Bytes.fromHexString('0x1234')), ], [ ethereum.Value.fromSignedBigInt(BigInt.fromString('2')), - ethereum.Value.fromAddress(Address.fromString(dao)), - ethereum.Value.fromAddress(Address.fromString(plugin)), + ethereum.Value.fromAddress(daoAddress), + ethereum.Value.fromAddress(pluginAddress), ethereum.Value.fromAddress(Address.fromString(ADDRESS_SIX)), ethereum.Value.fromBytes(Bytes.fromHexString('0x5678')), ], @@ -564,11 +640,11 @@ test('UninstallationPrepared event', function () { let event = createUninstallationPreparedEvent( ADDRESS_THREE, - dao, + daoEntityId, Bytes.fromHexString(setupId), - pluginSetupRepo, + pluginRepoEntityId, versionTuple, - plugin, + pluginEntityId, [ADDRESS_FOUR, ADDRESS_FIVE], Bytes.fromHexString('0x00'), permissions @@ -576,53 +652,60 @@ test('UninstallationPrepared event', function () { handleUninstallationPrepared(event); assert.entityCount('PluginPreparation', 1); - assert.fieldEquals('PluginPreparation', preparationId, 'id', preparationId); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, + 'id', + pluginPreparationEntityId + ); + assert.fieldEquals( + 'PluginPreparation', + pluginPreparationEntityId, 'installation', - installationIdString + pluginInstallationEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'creator', ADDRESS_THREE ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'preparedSetupId', setupId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'pluginRepo', - pluginSetupRepo + pluginRepoEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'pluginVersion', - pluginVersionId + pluginVersionEntityId ); assert.fieldEquals( 'PluginPreparation', - preparationId, + pluginPreparationEntityId, 'type', 'Uninstallation' ); - let pluginPreparation = PluginPreparation.load(preparationId); + let pluginPreparation = PluginPreparation.load(pluginPreparationEntityId); if (!pluginPreparation) { - throw new Error(`PluginPrepation with id ${preparationId} not found`); + throw new Error( + `PluginPrepation with id ${pluginPreparationEntityId} not found` + ); } assert.equals( ethereum.Value.fromBytesArray(pluginPreparation.helpers), @@ -632,46 +715,48 @@ test('UninstallationPrepared event', function () { assert.entityCount('PluginPermission', 2); for (let i = 0; i < permissions.length; i++) { - let permission = permissions[i]; - let operation = PERMISSION_OPERATIONS.get(permission[0].toI32()); - let permissionEntityId = `${preparationId}_${operation}_${permission[1] - .toAddress() - .toHexString()}_${permission[2].toAddress().toHexString()}_${permission[4] - .toBytes() - .toHexString()}`; + const permission = permissions[i]; + const operation = permission[0].toI32(); + const pluginPermissionEntityId = generatePluginPermissionEntityId( + pluginPreparationEntityId, + operation, + permission[1].toAddress(), + permission[2].toAddress(), + permission[4].toBytes() + ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'id', - permissionEntityId + pluginPermissionEntityId ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'operation', - operation || '' + PERMISSION_OPERATIONS.get(operation) || '' ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'where', permission[1].toAddress().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'who', permission[2].toAddress().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'permissionId', permission[4].toBytes().toHexString() ); assert.fieldEquals( 'PluginPermission', - permissionEntityId, + pluginPermissionEntityId, 'condition', permission[3].toAddress().toHexString() ); @@ -680,13 +765,13 @@ test('UninstallationPrepared event', function () { assert.entityCount('PluginInstallation', 1); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'state', 'UninstallPrepared' ); @@ -695,35 +780,42 @@ test('UninstallationPrepared event', function () { }); test('UninstallationApplied event', function () { - let dao = DAO_ADDRESS; - let plugin = ADDRESS_ONE; - let setupId = PLUGIN_SETUP_ID; - let installationId = getPluginInstallationId(dao, plugin); - if (!installationId) { - throw new Error('Failed to get installationId'); + let pluginInstallationEntityId = generatePluginInstallationEntityId( + daoAddress, + pluginAddress + ); + if (!pluginInstallationEntityId) { + throw new Error('Failed to get pluginInstallationEntityId'); } - let installationIdString = installationId.toHexString(); - let preparationId = `${installationIdString}_${setupId}`; + pluginInstallationEntityId = pluginInstallationEntityId as string; + const pluginPreparationEntityId = generatePluginPreparationEntityId( + pluginInstallationEntityId, + Bytes.fromHexString(setupId) + ); - let event = createUninstallationAppliedEvent(dao, plugin, setupId); + let event = createUninstallationAppliedEvent( + daoEntityId, + pluginEntityId, + setupId + ); handleUninstallationApplied(event); assert.entityCount('PluginInstallation', 1); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'dao', - dao.toLowerCase() + daoEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'appliedPreparation', - preparationId + pluginPreparationEntityId ); assert.fieldEquals( 'PluginInstallation', - installationIdString, + pluginInstallationEntityId, 'state', 'Uninstalled' ); diff --git a/packages/subgraph/tests/registry/daoRegistry.test.ts b/packages/subgraph/tests/registry/daoRegistry.test.ts index e7c76a0a1..85f279db6 100644 --- a/packages/subgraph/tests/registry/daoRegistry.test.ts +++ b/packages/subgraph/tests/registry/daoRegistry.test.ts @@ -2,6 +2,7 @@ import {Dao} from '../../generated/schema'; import {handleDAORegistered} from '../../src/registries/daoRegistry'; import {DAO_ADDRESS, ADDRESS_ONE} from '../constants'; import {createNewDaoEvent} from './utils'; +import {generateDaoEntityId} from '@aragon/osx-commons-subgraph'; import {Address} from '@graphprotocol/graph-ts'; import { assert, @@ -24,20 +25,21 @@ describe('DAORegistry', () => { // handle event handleDAORegistered(newDaoEvent); - let entityID = Address.fromString(DAO_ADDRESS).toHexString(); + const daoAddress = Address.fromString(DAO_ADDRESS); + const daoEntityId = generateDaoEntityId(daoAddress); // checks - assert.fieldEquals('Dao', entityID, 'id', entityID); + assert.fieldEquals('Dao', daoEntityId, 'id', daoEntityId); assert.fieldEquals( 'Dao', - entityID, + daoEntityId, 'creator', Address.fromString(ADDRESS_ONE).toHexString() ); - assert.fieldEquals('Dao', entityID, 'subdomain', 'mock-Dao'); + assert.fieldEquals('Dao', daoEntityId, 'subdomain', 'mock-Dao'); assert.fieldEquals( 'Dao', - entityID, + daoEntityId, 'createdAt', newDaoEvent.block.timestamp.toString() ); @@ -45,29 +47,33 @@ describe('DAORegistry', () => { test("Don't store subdomain for blocklisted DAO", () => { // Using an already blocklisted address for mainnet. This is unlikely to change - let entityID = '0x16070493aa513f91fc8957f14b7b7c6c0c41fbac'; + let denylistedEntityId = '0x16070493aa513f91fc8957f14b7b7c6c0c41fbac'; // create event. - let newDaoEvent = createNewDaoEvent(entityID, ADDRESS_ONE, 'mock-Dao'); + let newDaoEvent = createNewDaoEvent( + denylistedEntityId, + ADDRESS_ONE, + 'mock-Dao' + ); dataSourceMock.setNetwork('mainnet'); handleDAORegistered(newDaoEvent); // checks - assert.fieldEquals('Dao', entityID, 'id', entityID); + assert.fieldEquals('Dao', denylistedEntityId, 'id', denylistedEntityId); assert.fieldEquals( 'Dao', - entityID, + denylistedEntityId, 'creator', Address.fromString(ADDRESS_ONE).toHexString() ); assert.fieldEquals( 'Dao', - entityID, + denylistedEntityId, 'createdAt', newDaoEvent.block.timestamp.toString() ); - const daoEntity = Dao.load(entityID); + const daoEntity = Dao.load(denylistedEntityId); assert.assertNull(daoEntity!.subdomain); }); }); diff --git a/packages/subgraph/tests/registry/pluginRepoRegistry.test.ts b/packages/subgraph/tests/registry/pluginRepoRegistry.test.ts index 3e156147a..51f65b20e 100644 --- a/packages/subgraph/tests/registry/pluginRepoRegistry.test.ts +++ b/packages/subgraph/tests/registry/pluginRepoRegistry.test.ts @@ -1,19 +1,26 @@ import {handlePluginRepoRegistered} from '../../src/registries/pluginRepoRegistry'; import {ADDRESS_ONE} from '../constants'; import {createPluginRepoRegisteredEvent} from './utils'; +import {generatePluginRepoEntityId} from '@aragon/osx-commons-subgraph'; import {Address} from '@graphprotocol/graph-ts'; import {assert, clearStore, test} from 'matchstick-as/assembly/index'; test('Run plugin repo registry mappings with mock event', () => { - let id = Address.fromString(ADDRESS_ONE).toHexString(); + const pluginRepoAddress = Address.fromString(ADDRESS_ONE); + const pluginRepoEntityId = generatePluginRepoEntityId(pluginRepoAddress); let newRepoRegisteredEvent = createPluginRepoRegisteredEvent( 'plugin-repo', - ADDRESS_ONE + pluginRepoEntityId ); handlePluginRepoRegistered(newRepoRegisteredEvent); - assert.fieldEquals('PluginRepo', id, 'subdomain', 'plugin-repo'); + assert.fieldEquals( + 'PluginRepo', + pluginRepoEntityId, + 'subdomain', + 'plugin-repo' + ); clearStore(); }); diff --git a/packages/subgraph/tests/token/governance-erc20.test.ts b/packages/subgraph/tests/token/governance-erc20.test.ts index 9f68a3b3b..63d761524 100644 --- a/packages/subgraph/tests/token/governance-erc20.test.ts +++ b/packages/subgraph/tests/token/governance-erc20.test.ts @@ -3,6 +3,7 @@ import { handleDelegateVotesChanged, handleTransfer, } from '../../src/packages/token/governance-erc20'; +import {generateMemberEntityId} from '../../src/utils/ids'; import { ADDRESS_ONE, ADDRESS_SIX, @@ -13,7 +14,11 @@ import { } from '../constants'; import {ExtendedTokenVotingMember} from '../helpers/extended-schema'; import {createNewERC20TransferEvent, createTokenVotingMember} from './utils'; -import {BigInt, DataSourceContext} from '@graphprotocol/graph-ts'; +import { + generateEntityIdFromAddress, + generatePluginEntityId, +} from '@aragon/osx-commons-subgraph'; +import {Address, BigInt, DataSourceContext} from '@graphprotocol/graph-ts'; import { assert, afterEach, @@ -24,10 +29,19 @@ import { describe, } from 'matchstick-as'; +const pluginAddress = Address.fromString(ADDRESS_SIX); +const pluginEntityId = generatePluginEntityId(pluginAddress); +const fromAddress = Address.fromString(ADDRESS_ONE); +const memberAddress = fromAddress; +const toAddress = Address.fromString(ADDRESS_TWO); +const fromAddressHexString = fromAddress.toHexString(); +const memberAddressHexString = fromAddressHexString; +const toAddressHexString = toAddress.toHexString(); + describe('Governance ERC20', () => { beforeAll(() => { const context = new DataSourceContext(); - context.setString('pluginId', ADDRESS_SIX); + context.setString('pluginId', pluginEntityId); dataSourceMock.setContext(context); }); @@ -38,30 +52,35 @@ describe('Governance ERC20', () => { describe('handleTransfer', () => { test('it should create a new member of from', () => { const mockEvent = createNewERC20TransferEvent( - ADDRESS_ONE, - ADDRESS_TWO, + fromAddressHexString, + toAddressHexString, ONE_ETH ); handleTransfer(mockEvent); - const fromUserId = ADDRESS_ONE.concat('_').concat(ADDRESS_SIX); - assert.fieldEquals('TokenVotingMember', fromUserId, 'id', fromUserId); + const memberEntityId = generateMemberEntityId(fromAddress, pluginAddress); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'id', + memberEntityId + ); assert.fieldEquals( 'TokenVotingMember', - fromUserId, + memberEntityId, 'address', - ADDRESS_ONE + fromAddressHexString ); assert.fieldEquals( 'TokenVotingMember', - fromUserId, + memberEntityId, 'plugin', - ADDRESS_SIX + pluginEntityId ); assert.fieldEquals( 'TokenVotingMember', - fromUserId, + memberEntityId, 'balance', `-${ONE_ETH}` ); @@ -69,75 +88,115 @@ describe('Governance ERC20', () => { test('it should create a new member of to', () => { const mockEvent = createNewERC20TransferEvent( - ADDRESS_ONE, - ADDRESS_TWO, + fromAddressHexString, + toAddressHexString, ONE_ETH ); handleTransfer(mockEvent); - const toUserId = ADDRESS_TWO.concat('_').concat(ADDRESS_SIX); - assert.fieldEquals('TokenVotingMember', toUserId, 'id', toUserId); - assert.fieldEquals('TokenVotingMember', toUserId, 'address', ADDRESS_TWO); - assert.fieldEquals('TokenVotingMember', toUserId, 'plugin', ADDRESS_SIX); - assert.fieldEquals('TokenVotingMember', toUserId, 'balance', ONE_ETH); + const memberEntityId = generateMemberEntityId(toAddress, pluginAddress); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'id', + memberEntityId + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'address', + toAddressHexString + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'plugin', + pluginEntityId + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'balance', + ONE_ETH + ); }); test('it should update an existing from entity', () => { - const fromUserId = createTokenVotingMember( - ADDRESS_ONE, - ADDRESS_SIX, + const memberEntityId = createTokenVotingMember( + fromAddressHexString, + pluginEntityId, ONE_ETH + '0' ); const mockEvent = createNewERC20TransferEvent( - ADDRESS_ONE, - ADDRESS_TWO, + fromAddressHexString, + toAddressHexString, ONE_ETH ); handleTransfer(mockEvent); - assert.fieldEquals('TokenVotingMember', fromUserId, 'id', fromUserId); assert.fieldEquals( 'TokenVotingMember', - fromUserId, + memberEntityId, + 'id', + memberEntityId + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, 'address', - ADDRESS_ONE + fromAddressHexString ); assert.fieldEquals( 'TokenVotingMember', - fromUserId, + memberEntityId, 'plugin', - ADDRESS_SIX + pluginEntityId ); assert.fieldEquals( 'TokenVotingMember', - fromUserId, + memberEntityId, 'balance', BigInt.fromString(ONE_ETH).times(BigInt.fromString('9')).toString() ); }); test('it should update an existing to entity', () => { - const toUserId = createTokenVotingMember( - ADDRESS_TWO, - ADDRESS_SIX, + const memberEntityId = createTokenVotingMember( + toAddressHexString, + pluginEntityId, ONE_ETH + '0' ); const mockEvent = createNewERC20TransferEvent( - ADDRESS_ONE, - ADDRESS_TWO, + fromAddressHexString, + toAddressHexString, ONE_ETH ); handleTransfer(mockEvent); - assert.fieldEquals('TokenVotingMember', toUserId, 'id', toUserId); - assert.fieldEquals('TokenVotingMember', toUserId, 'address', ADDRESS_TWO); - assert.fieldEquals('TokenVotingMember', toUserId, 'plugin', ADDRESS_SIX); assert.fieldEquals( 'TokenVotingMember', - toUserId, + memberEntityId, + 'id', + memberEntityId + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'address', + ADDRESS_TWO + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, + 'plugin', + ADDRESS_SIX + ); + assert.fieldEquals( + 'TokenVotingMember', + memberEntityId, 'balance', BigInt.fromString(ONE_ETH).times(BigInt.fromString('11')).toString() ); @@ -146,11 +205,9 @@ describe('Governance ERC20', () => { describe('handleDelegateChanged', () => { test('it should create a member from `fromDelegate`.', () => { - let memberAddress = ADDRESS_ONE; - let pluginAddress = ADDRESS_SIX; let member = new ExtendedTokenVotingMember().withDefaultValues( - memberAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); let event = member.createEvent_DelegateChanged(); @@ -158,97 +215,103 @@ describe('Governance ERC20', () => { handleDelegateChanged(event); // expected changes - member.delegatee = [memberAddress, pluginAddress].join('_'); + member.delegatee = generateMemberEntityId(memberAddress, pluginAddress); member.assertEntity(); assert.entityCount('TokenVotingMember', 1); }); test('it should create a member from `toDelegate`.', () => { - let memberAddress = ADDRESS_ONE; - let pluginAddress = ADDRESS_SIX; + const memberTwoAddress = Address.fromString(ADDRESS_TWO); + const memberTwoAddressHexString = memberTwoAddress.toHexString(); let member = new ExtendedTokenVotingMember().withDefaultValues( - memberAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); let event = member.createEvent_DelegateChanged( - memberAddress, - ADDRESS_ONE, - ADDRESS_TWO + memberAddressHexString, + memberAddressHexString, + memberTwoAddressHexString ); handleDelegateChanged(event); // assert // expected changes - member.delegatee = ADDRESS_TWO.concat('_').concat(pluginAddress); + member.delegatee = generateMemberEntityId( + memberTwoAddress, + pluginAddress + ); member.assertEntity(); assert.entityCount('TokenVotingMember', 2); }); test('it should create a member for `delegator`, `fromDelegate` and `toDelegate`, and set delegatee as `toDelegate`.', () => { - let memberAddress = ADDRESS_ONE; - let pluginAddress = ADDRESS_SIX; let member = new ExtendedTokenVotingMember().withDefaultValues( - memberAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); + const oldDelegateeId = ADDRESS_TWO; + const newDelegateeAddress = Address.fromString(ADDRESS_THREE); + const newDelegateeId = generateEntityIdFromAddress(newDelegateeAddress); - let delegateeAddress = ADDRESS_THREE; let event = member.createEvent_DelegateChanged( - memberAddress, - ADDRESS_TWO, - delegateeAddress + memberAddressHexString, + oldDelegateeId, + newDelegateeId ); handleDelegateChanged(event); // assert // expected changes - member.delegatee = delegateeAddress.concat('_').concat(pluginAddress); + member.delegatee = generateMemberEntityId( + newDelegateeAddress, + pluginAddress + ); member.assertEntity(); assert.entityCount('TokenVotingMember', 3); }); test('it should update delegatee of an existing member', () => { - let memberAddress = ADDRESS_ONE; - let pluginAddress = ADDRESS_SIX; let member = new ExtendedTokenVotingMember().withDefaultValues( - memberAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); member.buildOrUpdate(); // there should be one member in the store assert.entityCount('TokenVotingMember', 1); - let fromDelegate = memberAddress; - let delegateeAddress = ADDRESS_TWO; + let fromDelegate = memberAddressHexString; + let delegateeAddress = Address.fromString(ADDRESS_TWO); + let delegateeId = generateEntityIdFromAddress(delegateeAddress); let event = member.createEvent_DelegateChanged( - memberAddress, + memberAddressHexString, fromDelegate, - delegateeAddress + delegateeId ); handleDelegateChanged(event); // assert // expected changes - member.delegatee = delegateeAddress.concat('_').concat(pluginAddress); + member.delegatee = generateMemberEntityId( + delegateeAddress, + pluginAddress + ); member.assertEntity(); // there must be the second member in the store for the delegatee assert.entityCount('TokenVotingMember', 2); }); }); - describe('handleDelegateChanged', () => { + describe('handleDelegatevotesChanged', () => { test('it should create member for delegate address', () => { - let memberAddress = ADDRESS_ONE; - let pluginAddress = ADDRESS_SIX; let member = new ExtendedTokenVotingMember().withDefaultValues( - memberAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); member.votingPower = BigInt.fromString('100'); let event = member.createEvent_DelegateVotesChanged('100', '0'); @@ -260,11 +323,9 @@ describe('Governance ERC20', () => { }); test('it should update delegateVotes of members', () => { - let memberAddress = ADDRESS_ONE; - let pluginAddress = ADDRESS_SIX; let member = new ExtendedTokenVotingMember().withDefaultValues( - memberAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); let newBalance = '111'; @@ -280,16 +341,17 @@ describe('Governance ERC20', () => { }); test('it should delete a member without voting power and balance and not delegating to another address', () => { - let memberOneAddress = ADDRESS_ONE; - let memberTwoAddress = ADDRESS_TWO; - let pluginAddress = ADDRESS_SIX; + const memberTwoAddress = Address.fromString(ADDRESS_TWO); + const memberTwoAddressHexString = + generateEntityIdFromAddress(memberTwoAddress); + let memberOne = new ExtendedTokenVotingMember().withDefaultValues( - memberOneAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); let memberTwo = new ExtendedTokenVotingMember().withDefaultValues( - memberTwoAddress, - pluginAddress + memberTwoAddressHexString, + pluginEntityId ); /* member one has 100 token delegated to member two*/ memberOne.balance = BigInt.fromString('100'); @@ -310,8 +372,8 @@ describe('Governance ERC20', () => { memberTwo.mockCall_delegatesCall( DAO_TOKEN_ADDRESS, - ADDRESS_TWO, - ADDRESS_TWO + memberTwoAddressHexString, + memberTwoAddressHexString ); handleDelegateVotesChanged(eventOne); @@ -327,16 +389,16 @@ describe('Governance ERC20', () => { }); test('it should not delete a member without voting power and balance, but delegating to another address', () => { - let memberOneAddress = ADDRESS_ONE; - let memberTwoAddress = ADDRESS_TWO; - let pluginAddress = ADDRESS_SIX; + const memberTwoAddress = Address.fromString(ADDRESS_TWO); + const memberTwoAddressHexString = + generateEntityIdFromAddress(memberTwoAddress); let memberOne = new ExtendedTokenVotingMember().withDefaultValues( - memberOneAddress, - pluginAddress + memberAddressHexString, + pluginEntityId ); let memberTwo = new ExtendedTokenVotingMember().withDefaultValues( - memberTwoAddress, - pluginAddress + memberTwoAddressHexString, + pluginEntityId ); /* member one has 100 token delegated to member two*/ memberOne.balance = BigInt.fromString('100'); @@ -357,8 +419,8 @@ describe('Governance ERC20', () => { memberTwo.mockCall_delegatesCall( DAO_TOKEN_ADDRESS, - ADDRESS_TWO, - ADDRESS_ONE + memberTwoAddressHexString, + memberAddressHexString ); handleDelegateVotesChanged(eventOne); diff --git a/packages/subgraph/tests/token/token-voting.test.ts b/packages/subgraph/tests/token/token-voting.test.ts index dd5e14dc6..fcdac8cd5 100644 --- a/packages/subgraph/tests/token/token-voting.test.ts +++ b/packages/subgraph/tests/token/token-voting.test.ts @@ -56,10 +56,9 @@ test('Run TokenVoting (handleProposalCreated) mappings with mock event', () => { // expected changes proposal.creationBlockNumber = BigInt.fromString(ONE); proposal.votingMode = VOTING_MODES.get(parseInt(VOTING_MODE)) as string; - // check TokenVotingProposal + // // check TokenVotingProposal proposal.assertEntity(); - // check TokenVotingPlugin tokenVotingPlugin.assertEntity(); clearStore(); diff --git a/packages/subgraph/tests/token/utils.ts b/packages/subgraph/tests/token/utils.ts index c8838bda5..3743522f0 100644 --- a/packages/subgraph/tests/token/utils.ts +++ b/packages/subgraph/tests/token/utils.ts @@ -11,6 +11,7 @@ import { ProposalExecuted, MembershipContractAnnounced, } from '../../generated/templates/TokenVoting/TokenVoting'; +import {generateMemberEntityId} from '../../src/utils/ids'; import { ADDRESS_ONE, DAO_ADDRESS, @@ -390,16 +391,19 @@ export function createTokenVotingMember( plugin: string, balance: string ): string { - const fromUserId = address.concat('_').concat(plugin); + const memberEntityId = generateMemberEntityId( + Address.fromString(address), + Address.fromString(plugin) // uses other plugin address to make sure that the code reuses the entity + ); - const user = new TokenVotingMember(fromUserId); + const user = new TokenVotingMember(memberEntityId); user.address = Address.fromString(address); user.plugin = plugin; // uses other plugin address to make sure that the code reuses the entity user.balance = BigInt.fromString(balance); - user.delegatee = fromUserId; + user.delegatee = memberEntityId; user.votingPower = BigInt.zero(); user.save(); - return fromUserId; + return memberEntityId; } diff --git a/yarn.lock b/yarn.lock index 25039d1f8..69ed5df39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,6 +6,12 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@aragon/osx-commons-configs/-/osx-commons-configs-0.0.2.tgz#8350da88c8fb93724de875589ba51eb7caa30936" integrity sha512-RCTig39oTekBF+M5FVLY8vKlNb8CW/RPRMpZtp5llTW1AOsPwVHj8SzmVSIHDdUAcbY1f34kLYEgJJBn7AwQrQ== +"@aragon/osx-commons-subgraph@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@aragon/osx-commons-subgraph/-/osx-commons-subgraph-0.0.3.tgz#27abe61e3cbae2c73faa8731edb43050ce229fe4" + integrity sha512-3p/1tXg5xySebYQ2T8+M/2zpfRSf+uXrtHywXgfZEa7okr9NmnoqCkl8HawRiGJ745Sw34ZDMsjUzONAJCbSeQ== + dependencies: + "@graphprotocol/graph-ts" "0.31.0" "@aragon/osx-ethers-v1.2.0@npm:@aragon/osx-ethers@1.2.0": version "1.2.0" @@ -1443,6 +1449,13 @@ which "2.0.2" yaml "1.10.2" +"@graphprotocol/graph-ts@0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.31.0.tgz#730668c0369828b31bef81e8d9bc66b9b48e3480" + integrity sha512-xreRVM6ho2BtolyOh2flDkNoGZximybnzUnF53zJVp0+Ed0KnAlO1/KOCUYw06euVI9tk0c9nA2Z/D5SIQV2Rg== + dependencies: + assemblyscript "0.19.10" + "@graphprotocol/graph-ts@^0.27.0": version "0.27.0" resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.27.0.tgz#948fe1716f6082964a01a63a19bcbf9ac44e06ff"