-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from aragon/f/OS-588_abstract-pluginRepo-plugin…
…Setup-ids F/ OS-588 Sbstract plugin repo & plugin setup ids
- Loading branch information
Showing
10 changed files
with
353 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name: Subgraph Tests | ||
on: | ||
push: | ||
paths: | ||
- 'subgraph/**' | ||
- '.github/workflows/subgraph-*.yml' | ||
|
||
env: | ||
working-directory: subgraph | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
working-directory: ${{env.working-directory}} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Install node | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: 16 | ||
- name: Install dependencies | ||
run: yarn install --pure-lockfile | ||
- name: Run Tests | ||
run: yarn run test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import {Address} from '@graphprotocol/graph-ts'; | ||
|
||
/** | ||
* Generates the DAO's ID using its address in hexadecimal format. | ||
* | ||
* @param dao - The address of the DAO. | ||
* @returns A hexadecimal string representation of the provided DAO address. | ||
*/ | ||
export function getDaoId(dao: Address): string { | ||
return dao.toHexString(); | ||
} | ||
|
||
// TODO: this is not complete, it will be done in it's own task. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import { | ||
Address, | ||
ByteArray, | ||
Bytes, | ||
crypto, | ||
ethereum | ||
} from '@graphprotocol/graph-ts'; | ||
import {PERMISSION_OPERATIONS} from '../utils/constants'; | ||
|
||
/** | ||
* Generates the plugin repository's ID using its address in hexadecimal format. | ||
* | ||
* @param pluginRepo - The address of the plugin repository. | ||
* @returns A hexadecimal string representation of the provided address. | ||
*/ | ||
export function getPluginRepoId(pluginRepo: Address): string { | ||
return pluginRepo.toHexString(); | ||
} | ||
|
||
/** | ||
* Generates the plugin setup's ID using its address in hexadecimal format. | ||
* | ||
* @param pluginSetup - The address of the plugin setup. | ||
* @returns A hexadecimal string representation of the provided address. | ||
*/ | ||
export function getPluginSetupId(pluginSetup: Address): string { | ||
return pluginSetup.toHexString(); | ||
} | ||
|
||
/** | ||
* Generates an installation ID for a plugin based on a DAO and plugin's address. | ||
* | ||
* @param dao - The address of the DAO. | ||
* @param plugin - The address of the plugin. | ||
* @returns A unique ID based on the DAO and plugin's address or null if the encoding fails. | ||
*/ | ||
export function getPluginInstallationId( | ||
dao: Address, | ||
plugin: Address | ||
): string | null { | ||
let installationIdTuple = new ethereum.Tuple(); | ||
installationIdTuple.push(ethereum.Value.fromAddress(dao)); | ||
installationIdTuple.push(ethereum.Value.fromAddress(plugin)); | ||
|
||
let installationIdTupleEncoded = ethereum.encode( | ||
ethereum.Value.fromTuple(installationIdTuple) | ||
); | ||
|
||
if (installationIdTupleEncoded) { | ||
return Bytes.fromHexString( | ||
crypto | ||
.keccak256( | ||
ByteArray.fromHexString(installationIdTupleEncoded.toHexString()) | ||
) | ||
.toHexString() | ||
).toHexString(); | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* Generates a preparation ID by merging plugin installation ID and plugin setup ID. | ||
* | ||
* @param pluginInstallationId - The installation ID of the plugin. | ||
* @param pluginSetupId - The preparedSetupId of the plugin emitted from `PluginSetupProcessor`. | ||
* Refer to the [PluginSetupProcessor contract](https://github.com/aragon/osx/blob/develop/packages/contracts/src/framework/plugin/setup/PluginSetupProcessorHelpers.sol) for more details. | ||
* @returns A concatenated ID string for plugin preparation. | ||
*/ | ||
export function getPluginPreparationId( | ||
pluginInstallationId: string, | ||
prepareSetupId: Bytes | ||
): string { | ||
const ids = [pluginInstallationId, prepareSetupId.toHexString()]; | ||
return ids.join('_'); | ||
} | ||
|
||
/** | ||
* Generates a unique ID for a plugin's release based on its repository and release number. | ||
* | ||
* @param pluginRepo - The address of the plugin repository. | ||
* @param release - The number corresponding to the plugin's release. | ||
* @returns An ID string for the plugin release. | ||
*/ | ||
export function getPluginReleaseId(pluginRepo: Address, release: i32): string { | ||
const ids = [getPluginRepoId(pluginRepo), release.toString()]; | ||
return ids.join('_'); | ||
} | ||
|
||
/** | ||
* Generates a unique ID for a plugin's version using its repository, release number, and build number. | ||
* | ||
* @param pluginRepo - The address of the plugin repository. | ||
* @param release - The release number of the plugin. | ||
* @param build - The build number for the specific version of the plugin. | ||
* @returns A unique ID string for the plugin version. | ||
*/ | ||
export function getPluginVersionId( | ||
pluginRepo: Address, | ||
release: i32, | ||
build: i32 | ||
): string { | ||
const ids = [ | ||
getPluginRepoId(pluginRepo), | ||
release.toString(), | ||
build.toString() | ||
]; | ||
return ids.join('_'); | ||
} | ||
|
||
/** | ||
* Generates a unique permission ID for a plugin based on multiple attributes including operation, addresses, and existing permission ID. | ||
* | ||
* @param pluginPreparationId - The ID from plugin preparation. | ||
* @param operation - The numerical code for the operation type. | ||
* @param where - The address specifying the location of the permission. | ||
* @param who - The address specifying the entity of the permission. | ||
* @param permissionId - An existing permission ID. | ||
* @returns A concatenated unique ID string for the plugin permission. | ||
*/ | ||
export function getPluginPermissionId( | ||
pluginPreparationId: string, | ||
operation: i32, | ||
where: Address, | ||
who: Address, | ||
permissionId: Bytes | ||
): string { | ||
const operationId = PERMISSION_OPERATIONS.get(operation); | ||
const ids = [ | ||
pluginPreparationId, | ||
operationId, | ||
where.toHexString(), | ||
who.toHexString(), | ||
permissionId.toHexString() | ||
]; | ||
|
||
return ids.join('_'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './ids'; | ||
export * from './ids/dao'; | ||
export * from './ids/pluginRepo'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const PERMISSION_OPERATIONS = new Map<number, string>() | ||
.set(0, 'Grant') | ||
.set(1, 'Revoke') | ||
.set(2, 'GrantWithCondition'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
export const ADDRESS_ONE = '0x0000000000000000000000000000000000000001'; | ||
export const ADDRESS_TWO = '0x0000000000000000000000000000000000000002'; | ||
|
||
export const DUMMY_BYTES32_HEX = | ||
'0x0000000000000000000000000000000000000000000000000000000000000000'; | ||
export const DUMMY_INSTALLATION_ID = | ||
'0x000f1e7f040a60eb32b1b2348cf41924f85e221648a4d0a5ba66d2dea1122ee6'; |
17 changes: 5 additions & 12 deletions
17
subgraph/tests/ids.test.ts → subgraph/tests/ids/dao.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import {Address, Bytes, crypto} from '@graphprotocol/graph-ts'; | ||
import {assert, describe, log, test} from 'matchstick-as/assembly/index'; | ||
import { | ||
getPluginRepoId, | ||
getPluginSetupId, | ||
getPluginInstallationId, | ||
getPluginPreparationId, | ||
getPluginReleaseId, | ||
getPluginVersionId, | ||
getPluginPermissionId | ||
} from '../../src'; | ||
import { | ||
ADDRESS_ONE, | ||
ADDRESS_TWO, | ||
DUMMY_BYTES32_HEX, | ||
DUMMY_INSTALLATION_ID | ||
} from '../constants'; | ||
import {PERMISSION_OPERATIONS} from '../../src/utils/constants'; | ||
|
||
describe('PluginRepo ID generation', () => { | ||
test('`getPluginRepoId` should return the hexadecimal representation of the provided address', () => { | ||
// Constants | ||
const PLUGIN_REPO_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
|
||
assert.stringEquals(getPluginRepoId(PLUGIN_REPO_ADDRESS), ADDRESS_ONE); | ||
}); | ||
|
||
test('`getPluginSetupId` should return the hexadecimal representation of the provided address', () => { | ||
// Constants | ||
const PLUGIN_SETUP_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
|
||
assert.stringEquals(getPluginSetupId(PLUGIN_SETUP_ADDRESS), ADDRESS_ONE); | ||
}); | ||
|
||
test('`getPluginInstallationId` should return a unique ID based on the DAO and plugins address', () => { | ||
// Constants | ||
const DAO_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
const PLUGIN_ADDRESS = Address.fromString(ADDRESS_TWO); | ||
|
||
// Generate the pluginInstallationId. | ||
const pluginInstallationId = getPluginInstallationId( | ||
DAO_ADDRESS, | ||
PLUGIN_ADDRESS | ||
); | ||
|
||
if (pluginInstallationId) { | ||
const expectedEncodedBytes = Bytes.fromHexString( | ||
'0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002' | ||
); | ||
|
||
const expectedId = Bytes.fromHexString( | ||
crypto.keccak256(expectedEncodedBytes).toHexString() | ||
).toHexString(); | ||
|
||
assert.stringEquals(pluginInstallationId, expectedId); | ||
|
||
// The test is done. | ||
return; | ||
} | ||
|
||
// Test should fail if `pluginInstallationId` is null. | ||
assert.assertTrue(false); | ||
}); | ||
|
||
test('`getPluginPreparationId` should return a concatenated ID string for plugin preparation', () => { | ||
// Constants | ||
const DAO_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
const PLUGIN_ADDRESS = Address.fromString(ADDRESS_TWO); | ||
|
||
// Generate the pluginInstallationId. | ||
const pluginInstallationId = getPluginInstallationId( | ||
DAO_ADDRESS, | ||
PLUGIN_ADDRESS | ||
); | ||
|
||
if (pluginInstallationId) { | ||
const pluginSetupId = Bytes.fromHexString(DUMMY_BYTES32_HEX); | ||
|
||
// Generate the pluginPreparationId. | ||
const pluginPreparationId = getPluginPreparationId( | ||
pluginInstallationId, | ||
pluginSetupId | ||
); | ||
|
||
// Expected result | ||
const expectedPreparationId = `${pluginInstallationId}_${DUMMY_BYTES32_HEX}`; | ||
|
||
assert.stringEquals(pluginPreparationId, expectedPreparationId); | ||
|
||
// test is done. | ||
return; | ||
} | ||
|
||
// Test should fail if `pluginInstallationId` is null. | ||
assert.assertTrue(false); | ||
}); | ||
|
||
test('`getPluginReleaseId` should return an ID string for the plugin release.', () => { | ||
// Constants | ||
const PLUGIN_REPO_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
const PLUGIN_RELEASE: i32 = 1; | ||
|
||
// Generate the pluginReleaseId. | ||
const pluginReleaseId = getPluginReleaseId( | ||
PLUGIN_REPO_ADDRESS, | ||
PLUGIN_RELEASE | ||
); | ||
|
||
const expectedId = `${ADDRESS_ONE}_${PLUGIN_RELEASE}`; | ||
|
||
assert.stringEquals(pluginReleaseId, expectedId); | ||
}); | ||
|
||
test('`getPluginVersionId` should return an ID string for the plugin version.', () => { | ||
// Constants | ||
const PLUGIN_REPO_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
const PLUGIN_RELEASE: i32 = 1; | ||
const PLUGIN_BUILD: i32 = 2; | ||
|
||
// Generate the pluginVersionId. | ||
const pluginVersionId = getPluginVersionId( | ||
PLUGIN_REPO_ADDRESS, | ||
PLUGIN_RELEASE, | ||
PLUGIN_BUILD | ||
); | ||
|
||
const expectedId = `${ADDRESS_ONE}_${PLUGIN_RELEASE}_${PLUGIN_BUILD}`; | ||
|
||
assert.stringEquals(pluginVersionId, expectedId); | ||
}); | ||
|
||
test('`getPluginPermissionId` should return a concatenated unique ID string for the plugin permission', () => { | ||
// Constants | ||
const OPERATION: i32 = 1; | ||
const WHERE_ADDRESS = Address.fromString(ADDRESS_ONE); | ||
const WHO_ADDRESS = Address.fromString(ADDRESS_TWO); | ||
const PERMISSION_ID = Bytes.fromHexString(DUMMY_BYTES32_HEX); | ||
const PLUGIN_PREPARATION_ID = getPluginPreparationId( | ||
DUMMY_BYTES32_HEX, | ||
Bytes.fromHexString(DUMMY_BYTES32_HEX) | ||
); | ||
|
||
// Generate the pluginPermissionId | ||
const pluginPermissionId = getPluginPermissionId( | ||
PLUGIN_PREPARATION_ID, | ||
OPERATION, | ||
WHERE_ADDRESS, | ||
WHO_ADDRESS, | ||
PERMISSION_ID | ||
); | ||
|
||
const expectedId = `${PLUGIN_PREPARATION_ID}_${PERMISSION_OPERATIONS.get( | ||
OPERATION | ||
)}_${WHERE_ADDRESS.toHexString()}_${WHO_ADDRESS.toHexString()}_${PERMISSION_ID.toHexString()}`; | ||
|
||
assert.stringEquals(pluginPermissionId, expectedId); | ||
}); | ||
}); |