Skip to content
This repository has been archived by the owner on May 8, 2023. It is now read-only.

Commit

Permalink
Fix role assignment, add parseRoles utility
Browse files Browse the repository at this point in the history
  • Loading branch information
chmanie committed Apr 13, 2023
1 parent 73094eb commit 239ee2e
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 35 deletions.
26 changes: 26 additions & 0 deletions docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,32 @@ value is NonNullable<T\>

___

### parseRoles

**parseRoles**(`roles`): [`ColonyRole`](enums/ColonyRole.md)[]

Parses a binary role integer into a [ColonyRole](enums/ColonyRole.md) array

When getting multiple roles from contract methods or events they are
usually formatted as a binary number. Here the least significant bit is
the role with the index 0 (Recovery).

E.g. 5 = 0b00101 equals Recovery and Arbitration

This function parses these binary integers into a [ColonyRole](enums/ColonyRole.md) array.

#### Parameters

| Name | Type | Description |
| :------ | :------ | :------ |
| `roles` | `string` | A hex string (e.g. 0x3 = 0b11 equals Recovery and Root roles) |

#### Returns

[`ColonyRole`](enums/ColonyRole.md)[]

___

### toEth

**toEth**(`num`): `string`
Expand Down
50 changes: 29 additions & 21 deletions docs/api/classes/ColonyNetwork.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,16 @@ ___

### createColony

**createColony**(`tokenAddress`, `label`, `metadata`): [`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\>
**createColony**(`token`, `label`, `metadata`): [`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColonyForFrontend"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` ; `tokenAddress`: `string` ; `tokenAuthorityAddress`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\>

Create a new colony with metadata

Creates a new colony with IPFS metadata. To edit metadata at a later point you can call the [Colony.editColony](Colony.md#editcolony) method.

**`Remarks`**

There is more to creating a fully functional colony that can be used within the dapp than just calling this function. See the [Colony Creation Guide](../../guides/colony-creation.md).
There is more to creating a fully functional colony that can be used within the dapp than just calling this function.
See the [Colony Creation Guide](../../guides/colony-creation.md).

**`Example`**

Expand All @@ -67,28 +68,30 @@ import { Tokens } from '@colony/sdk';
// (forced transaction example)
// (also notice that this requires an upload-capable IPFS adapter)
await colonyNetwork.createColony(
// Use USDC on Gnosis chain as the native token
'0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', {
// Create a new token ('COOL') for this Colony
{ name: 'Cool token', symbol: 'COOL' },
'coolony',
{
colonyDisplayName: 'Cool Colony',
// IPFS hash to an image file
colonyAvatarHash: 'QmS26o1Cmsrx7iw1SSFGEcy22TVDq6VmEZ4XNjpWFyaKUe',
// List of token addresses that the Colony should be initialized with (can be changed later) - excluding ETH and the native token from above
colonyTokens: [Tokens.CLNY],
}).tx();
colonyTokens: [Tokens.Gnosis.CLNY],
}).tx();
})();
```

#### Parameters

| Name | Type | Description |
| :------ | :------ | :------ |
| `tokenAddress` | `string` | - |
| `label` | `string` | - |
| `token` | `string` \| `TokenData` | Create a new ERC20-compatible token by passing in its name and symbol or use an existing token by passing in its contract address |
| `label` | `string` | The Colony's label. This is going to be part of the URL to look up the Colony within the dApp |
| `metadata` | `string` \| [`ColonyMetadata`](../interfaces/ColonyMetadata.md) | The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [ColonyMetadata](../interfaces/ColonyMetadata.md) is provided directly (as opposed to a [CID](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats) for a JSON file) this requires an [IpfsAdapter](../interfaces/IpfsAdapter.md) that can upload and pin to IPFS (like the [PinataAdapter](PinataAdapter.md)). See its documentation for more information. |

#### Returns

[`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\>
[`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColonyForFrontend"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` ; `tokenAddress`: `string` ; `tokenAuthorityAddress`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\>

A transaction creator

Expand All @@ -98,7 +101,9 @@ A transaction creator
| :------ | :------ | :------ |
| `colonyId` | BigNumber | Auto-incremented integer id of the colony |
| `colonyAddress` | string | Address of the newly deployed colony contract |
| `token` | string | Address of the token that is used as the colony's native token |
| `tokenAddress` | string | Address of the token that is used as the colony's native token |
| `tokenAuthorityAddress` | string | Address of the token authority (the token's permission manager) contract |
| `token` | string | Alias of `token`
| `metadata` | string | IPFS CID of metadata attached to this transaction |

#### Metadata
Expand All @@ -111,15 +116,16 @@ A transaction creator
| `colonyAvatarHash` | string | An IPFS hash for a Colony logo (make it 200x200px) |
| `colonyTokens` | string[] | A list of additional tokens that should be in the colony's "address book" |

**createColony**(`tokenAddress`, `label`): [`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>
**createColony**(`token`, `label`): [`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColonyForFrontend"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` ; `tokenAddress`: `string` ; `tokenAuthorityAddress`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>

Create a new Colony without metadata

Creates a new Colony without IPFS metadata. To add metadata at a later point you can call the [Colony.editColony](Colony.md#editcolony) method.

**`Remarks`**

There is more to creating a fully functional colony that can be used within the dapp than just calling this function. See the [Colony Creation Guide](../../guides/colony-creation.md).
There is more to creating a fully functional colony that can be used within the dapp than just calling this function.
See the [Colony Creation Guide](../../guides/colony-creation.md).

**`Example`**

Expand All @@ -130,21 +136,21 @@ There is more to creating a fully functional colony that can be used within the
// (forced transaction example)
await colonyNetwork
// Use USDC on Gnosis chain as the native token
.createColony('0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83')
.createColony('0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', 'coolony')
.tx();
})();
```

#### Parameters

| Name | Type |
| :------ | :------ |
| `tokenAddress` | `string` |
| `label` | `string` |
| Name | Type | Description |
| :------ | :------ | :------ |
| `token` | `string` \| `TokenData` | Create a new ERC20-compatible token by passing in its name and symbol or use an existing token by passing in its contract address |
| `label` | `string` | The Colony's label. This is going to be part of the URL to look up the Colony within the dApp |

#### Returns

[`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>
[`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"createColonyForFrontend"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` ; `tokenAddress`: `string` ; `tokenAuthorityAddress`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>

A transaction creator

Expand All @@ -154,19 +160,21 @@ A transaction creator
| :------ | :------ | :------ |
| `colonyId` | BigNumber | Auto-incremented integer id of the colony |
| `colonyAddress` | string | Address of the newly deployed colony contract |
| `token` | string | Address of the token that is used as the colony's native token |
| `tokenAddress` | string | Address of the token that is used as the colony's native token |
| `tokenAuthorityAddress` | string | Address of the token authority (the token's permission manager) contract |
| `token` | string | Alias of `token`

___

### deployToken

**deployToken**(`name`, `symbol`, `decimals?`): [`MetaTxCreator`](MetaTxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>

Deploy a "special" colony ERC20 token
Deploy a "special" Colony ERC20 token

If there is not token yet that should be used with the Colony, this is the canonical way to create one.

This is a supercharged ERC20 token contract, that not only has a permissioned `mint` function (that can be used from the colony) but also supports Metatransactions. In order to fully use its permissioned system with a colony, some extra steps have to be taken. See the [Colony Creation Guide](../../guides/colony-creation.md).
This is a supercharged ERC20 token contract, that not only has a permissioned `mint` function (that can be used from the colony) but also supports Metatransactions. In order to fully use its permissioned system with a Colony, some extra steps have to be taken. See the [Colony Creation Guide](../../guides/colony-creation.md).

**`Remarks`**

Expand Down
4 changes: 2 additions & 2 deletions docs/api/classes/ColonyToken.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ ___

### setAuthority

**setAuthority**(`tokenAuthorityAddress`): [`MetaTxCreator`](MetaTxCreator.md)<`MetaTxToken`, ``"setAuthority"``, { `authority?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>
**setAuthority**(`address`): [`MetaTxCreator`](MetaTxCreator.md)<`MetaTxToken`, ``"setAuthority"``, { `authority?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>

Sets the address of the TokenAuthority for this token

Expand Down Expand Up @@ -207,7 +207,7 @@ import { w } from '@colony/sdk';

| Name | Type | Description |
| :------ | :------ | :------ |
| `tokenAuthorityAddress` | `string` | Address of the TokenAuthority contract |
| `address` | `string` | Address of the TokenAuthority contract |

#### Returns

Expand Down
37 changes: 37 additions & 0 deletions examples/node/roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { providers, Wallet } from 'ethers';
import { ColonyRole } from '@colony/colony-js';

import { ColonyNetwork, ColonyRpcEndpoint } from '../../src';

const provider = new providers.JsonRpcProvider(ColonyRpcEndpoint.Gnosis);

if (!process.env.PRIVATE_KEY) {
throw new Error(
`Please provide a valid private key as an environment variable: PRIVATE_KEY`,
);
}

const signer = new Wallet(process.env.PRIVATE_KEY as string).connect(provider);

// Set the Administration and Funding permissions for the OneTxPayment extension of a Colony
const start = async () => {
const colonyNetwork = await ColonyNetwork.init(signer);
const colony = await colonyNetwork.getColony(
'0xA6fD5655c1249f1349D0917E732813Ebd9439A54',
);
// await colony
// .setRoles('0xA75b108808584A15ceEbF8f6CAc19EaD91cAbCd2', [
// ColonyRole.Administration,
// ColonyRole.Funding,
// ])
// .tx();
const roles = await colony.getRoles(
'0xA75b108808584A15ceEbF8f6CAc19EaD91cAbCd2',
);
console.info(
'Roles',
roles.map((role) => ColonyRole[role]),
);
};

start();
16 changes: 4 additions & 12 deletions src/ColonyNetwork/Colony.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
import type { Expand, Parameters, ParametersFrom2 } from '../types';

import { PermissionConfig, TxConfig, ColonyTxCreator } from '../TxCreator';
import { extractEvent, extractCustomEvent } from '../utils';
import { extractEvent, extractCustomEvent, parseRoles } from '../utils';
import { ColonyToken } from './ColonyToken';
import { ERC20Token } from './ERC20Token';
import { ColonyNetwork } from './ColonyNetwork';
Expand Down Expand Up @@ -1063,15 +1063,7 @@ export class Colony {
*/
async getRoles(address: string, teamId: BigNumberish = Id.RootDomain) {
const roleString = await this.colonyClient.getUserRoles(address, teamId);
const rolesNum = parseInt(roleString, 16);
const roles = [] as ColonyRole[];
for (let i = 0; i < ColonyRole.LAST_ROLE; i += 1) {
// eslint-disable-next-line no-bitwise
if (rolesNum & (1 << i)) {
roles.push(i as ColonyRole);
}
}
return roles;
return parseRoles(roleString);
}

/**
Expand Down Expand Up @@ -1131,7 +1123,7 @@ export class Colony {
.concat(roles)
.reduce((acc, current) => acc | (1 << current), 0) | oldRoles;
/* eslint-enable no-bitwise */
const hexRoles = utils.hexZeroPad(`0x${newRoles}`, 32);
const hexRoles = utils.hexZeroPad(`0x${newRoles.toString(16)}`, 32);
return [address, teamId, hexRoles] as [string, BigNumber, string];
},
{
Expand Down Expand Up @@ -1192,7 +1184,7 @@ export class Colony {
.reduce((acc, current) => acc & ~(1 << current), 0b11111) &
oldRoles;
/* eslint-enable no-bitwise */
const hexRoles = utils.hexZeroPad(`0x${newRoles}`, 32);
const hexRoles = utils.hexZeroPad(`0x${newRoles.toString(16)}`, 32);
return [address, teamId, hexRoles] as [string, BigNumber, string];
},
{
Expand Down
28 changes: 28 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { BigNumberish, ContractReceipt, utils } from 'ethers';
import { ColonyRole } from '@colony/colony-js';

import type { Log } from '@ethersproject/abstract-provider';
import type { JsonRpcProvider } from '@ethersproject/providers';
import type { Interface } from '@ethersproject/abi';
Expand Down Expand Up @@ -120,3 +122,29 @@ export const toWei = (num: string) => utils.parseEther(num);
* ```
*/
export const w = (str: TemplateStringsArray) => toWei(str[0]);

/**
* Parses a binary role integer into a [[ColonyRole]] array
*
* When getting multiple roles from contract methods or events they are
* usually formatted as a binary number. Here the least significant bit is
* the role with the index 0 (Recovery).
*
* E.g. 5 = 0b00101 equals Recovery and Arbitration
*
* This function parses these binary integers into a [[ColonyRole]] array.
*
* @param roles - A hex string (e.g. 0x3 = 0b11 equals Recovery and Root roles)
*
*/
export const parseRoles = (roles: string) => {
const rolesNum = parseInt(roles, 16);
const result = [] as ColonyRole[];
for (let i = 0; i < ColonyRole.LAST_ROLE; i += 1) {
// eslint-disable-next-line no-bitwise
if (rolesNum & (1 << i)) {
result.push(i as ColonyRole);
}
}
return result;
};

0 comments on commit 239ee2e

Please sign in to comment.