From eeba1d2ee3c3e9e55229f0dacc0530f656abe3da Mon Sep 17 00:00:00 2001 From: chmanie Date: Mon, 28 Nov 2022 22:48:06 +0900 Subject: [PATCH 01/12] Add functions needed for colony creation --- docs/api/README.md | 1 + docs/api/classes/Colony.md | 66 +++++++++++++++- docs/api/classes/ColonyNetwork.md | 59 +++++++++++++++ docs/api/classes/ColonyToken.md | 48 ++++++++++++ docs/api/classes/TxCreator.md | 3 +- docs/api/classes/VotingReputation.md | 22 ++++++ docs/api/enums/SupportedExtension.md | 13 ++++ src/ColonyNetwork/Colony.ts | 88 ++++++++++++++++++++- src/ColonyNetwork/ColonyNetwork.ts | 105 +++++++++++++++++++++++++- src/ColonyNetwork/ColonyToken.ts | 33 ++++++++ src/ColonyNetwork/OneTxPayment.ts | 19 ++++- src/ColonyNetwork/TxCreator.ts | 46 +++++++---- src/ColonyNetwork/VotingReputation.ts | 16 +++- src/ColonyNetwork/index.ts | 2 +- 14 files changed, 489 insertions(+), 32 deletions(-) create mode 100644 docs/api/enums/SupportedExtension.md diff --git a/docs/api/README.md b/docs/api/README.md index 5b8bf5bc..98bc1e14 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -13,6 +13,7 @@ - [MetadataType](enums/MetadataType.md) - [MotionState](enums/MotionState.md) - [Network](enums/Network.md) +- [SupportedExtension](enums/SupportedExtension.md) - [TeamColor](enums/TeamColor.md) - [Vote](enums/Vote.md) diff --git a/docs/api/classes/Colony.md b/docs/api/classes/Colony.md index 60246efc..09b193e7 100644 --- a/docs/api/classes/Colony.md +++ b/docs/api/classes/Colony.md @@ -42,9 +42,9 @@ ___ ___ -### SupportedVersions +### supportedVersions -▪ `Static` **SupportedVersions**: ``10``[] +▪ `Static` **supportedVersions**: ``10``[] The currently supported Colony version. If a Colony is not on this version it has to be upgraded. If this is not an option, Colony SDK might throw errors at certain points. Usage of ColonyJS is advised in these cases @@ -361,6 +361,22 @@ A Team object ___ +### installExtension + +▸ **installExtension**(`extension`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"installExtension"``, { `colony?`: `string` ; `extensionId?`: `string` ; `version?`: `BigNumber` }, [`MetadataType`](../enums/MetadataType.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `extension` | [`SupportedExtension`](../enums/SupportedExtension.md) | + +#### Returns + +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"installExtension"``, { `colony?`: `string` ; `extensionId?`: `string` ; `version?`: `BigNumber` }, [`MetadataType`](../enums/MetadataType.md)\> + +___ + ### makeArbitraryTransaction ▸ **makeArbitraryTransaction**(`target`, `action`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"makeArbitraryTransactions"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\> @@ -463,3 +479,49 @@ A [TxCreator](TxCreator.md) | `toPot` | BigNumber | The target funding pot | | `amount` | BigNumber | The amount that was transferred | | `token` | string | The token address being transferred | + +___ + +### setAdministrationRole + +▸ **setAdministrationRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | +| `teamId` | `BigNumberish` | +| `set` | `boolean` | + +#### Returns + +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> + +___ + +### setFundingRole + +▸ **setFundingRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | +| `teamId` | `BigNumberish` | +| `set` | `boolean` | + +#### Returns + +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> + +___ + +### getLatestSupportedVersion + +▸ `Static` **getLatestSupportedVersion**(): ``10`` + +#### Returns + +``10`` diff --git a/docs/api/classes/ColonyNetwork.md b/docs/api/classes/ColonyNetwork.md index b271619c..1fb8e8fc 100644 --- a/docs/api/classes/ColonyNetwork.md +++ b/docs/api/classes/ColonyNetwork.md @@ -54,8 +54,67 @@ ___ • **networkClient**: `ColonyNetworkClient` +___ + +### signerOrProvider + +• **signerOrProvider**: `SignerOrProvider` + ## Methods +### createColony + +▸ **createColony**(`tokenAddress`, `colonyLabel`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenAddress` | `string` | +| `colonyLabel` | `string` | + +#### Returns + +`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> + +___ + +### createColonyWithMetadata + +▸ **createColonyWithMetadata**(`tokenAddress`, `colonyLabel`, `metadata`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenAddress` | `string` | +| `colonyLabel` | `string` | +| `metadata` | `string` \| `ColonyMetadata` | + +#### Returns + +`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> + +___ + +### deployToken + +▸ **deployToken**(`name`, `symbol`, `decimals?`): `Promise`<`string`\> + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `name` | `string` | `undefined` | +| `symbol` | `string` | `undefined` | +| `decimals` | `number` | `18` | + +#### Returns + +`Promise`<`string`\> + +___ + ### getColony ▸ **getColony**(`address`): `Promise`<[`Colony`](Colony.md)\> diff --git a/docs/api/classes/ColonyToken.md b/docs/api/classes/ColonyToken.md index 64ff0d2e..c130ed63 100644 --- a/docs/api/classes/ColonyToken.md +++ b/docs/api/classes/ColonyToken.md @@ -2,6 +2,12 @@ ## Properties +### address + +• **address**: `string` + +___ + ### tokenLockingClient • **tokenLockingClient**: `TokenLockingClient` @@ -53,6 +59,22 @@ A tupel of event data and contract receipt ___ +### deployAuthority + +▸ **deployAuthority**(`allowedToTransfer?`): `Promise`<`string`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `allowedToTransfer?` | `string`[] | + +#### Returns + +`Promise`<`string`\> + +___ + ### deposit ▸ **deposit**(`amount`): `Promise`<[{ `amount?`: `BigNumber` ; `token?`: `string` ; `user?`: `string` }, `ContractReceipt`]\> @@ -184,6 +206,32 @@ A [TxCreator](TxCreator.md) ___ +### setAuthority + +▸ **setAuthority**(`tokenAuthorityAddress`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenAuthorityAddress` | `string` | + +#### Returns + +`Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> + +___ + +### setupColonyAsOwner + +▸ **setupColonyAsOwner**(): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setOwner"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> + +#### Returns + +`Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setOwner"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> + +___ + ### symbol ▸ **symbol**(): `Promise`<`string`\> diff --git a/docs/api/classes/TxCreator.md b/docs/api/classes/TxCreator.md index 68375d40..2c521100 100644 --- a/docs/api/classes/TxCreator.md +++ b/docs/api/classes/TxCreator.md @@ -46,7 +46,8 @@ Learn more about these functions in their individual documentation | :------ | :------ | | `__namedParameters` | `Object` | | `__namedParameters.args` | `unknown`[] \| () => `Promise`<`unknown`[]\> | -| `__namedParameters.colony` | [`Colony`](Colony.md) | +| `__namedParameters.colony?` | [`Colony`](Colony.md) | +| `__namedParameters.colonyNetwork` | [`ColonyNetwork`](ColonyNetwork.md) | | `__namedParameters.contract` | `C` | | `__namedParameters.eventData?` | (`receipt`: `ContractReceipt`) => `Promise`<`E`\> | | `__namedParameters.metadataType?` | `MD` | diff --git a/docs/api/classes/VotingReputation.md b/docs/api/classes/VotingReputation.md index 23a85c0f..13099a62 100644 --- a/docs/api/classes/VotingReputation.md +++ b/docs/api/classes/VotingReputation.md @@ -102,6 +102,18 @@ You can - at any point in the lifecycle inspect the current state of a Motion. U • **address**: `string` +___ + +### supportedVersions + +▪ `Static` **supportedVersions**: ``7``[] + +___ + +### type + +▪ `Static` **type**: [`IVotingReputation`](../enums/Extension.md#ivotingreputation) + ## Methods ### approveStake @@ -427,3 +439,13 @@ A tupel of event data and contract receipt | :------ | :------ | :------ | | `motionId` | BigNumber | ID of the motion created | | `voter` | string | The address of the user who voted | + +___ + +### getLatestSupportedVersion + +▸ `Static` **getLatestSupportedVersion**(): ``7`` + +#### Returns + +``7`` diff --git a/docs/api/enums/SupportedExtension.md b/docs/api/enums/SupportedExtension.md new file mode 100644 index 00000000..ca24938e --- /dev/null +++ b/docs/api/enums/SupportedExtension.md @@ -0,0 +1,13 @@ +# Enumeration: SupportedExtension + +## Enumeration Members + +### motion + +• **motion** = ``"motion"`` + +___ + +### oneTx + +• **oneTx** = ``"oneTx"`` diff --git a/src/ColonyNetwork/Colony.ts b/src/ColonyNetwork/Colony.ts index a1d37fb5..1b71c59e 100644 --- a/src/ColonyNetwork/Colony.ts +++ b/src/ColonyNetwork/Colony.ts @@ -6,16 +6,20 @@ import { IBasicMetaTransaction, getChildIndex, getPermissionProofs, + isExtensionCompatible, } from '@colony/colony-js'; import { AnnotationEventObject, + ColonyAdministrationRoleSetEventObject, ColonyDataTypes, + ColonyFundingRoleSetEventObject, ColonyFundsClaimed_address_uint256_uint256_EventObject, // eslint-disable-next-line max-len ColonyFundsMovedBetweenFundingPots_address_uint256_uint256_uint256_address_EventObject, DomainAdded_uint256_EventObject, DomainDeprecatedEventObject, DomainMetadataEventObject, + ExtensionInstalledEventObject, FundingPotAddedEventObject, } from '@colony/colony-js/extras'; import { @@ -35,6 +39,17 @@ import { PermissionConfig, TxCreator } from './TxCreator'; export type SupportedColonyClient = ColonyClientV10; export type SupportedColonyMethods = SupportedColonyClient['functions']; + +export enum SupportedExtension { + motion = 'motion', + oneTx = 'oneTx', +} + +const supportedExtensionMap = { + [SupportedExtension.motion]: VotingReputation, + [SupportedExtension.oneTx]: OneTxPayment, +} as const; + export interface SupportedExtensions { motions?: VotingReputation; oneTx?: OneTxPayment; @@ -44,10 +59,12 @@ export class Colony { /** The currently supported Colony version. If a Colony is not on this version it has to be upgraded. * If this is not an option, Colony SDK might throw errors at certain points. Usage of ColonyJS is advised in these cases */ - static SupportedVersions: 10[] = [10]; + static supportedVersions: 10[] = [10]; private colonyClient: SupportedColonyClient; + signerOrProvider: SignerOrProvider; + address: string; colonyNetwork: ColonyNetwork; @@ -61,8 +78,6 @@ export class Colony { ext: SupportedExtensions; - signerOrProvider: SignerOrProvider; - version: number; /** @@ -88,6 +103,10 @@ export class Colony { this.version = colonyClient.clientVersion; } + static getLatestSupportedVersion() { + return Colony.supportedVersions[Colony.supportedVersions.length - 1]; + } + /** * Creates a new [[TxCreator]] for non-permissioned Colony transactions * @internal @@ -118,6 +137,7 @@ export class Colony { ) { return new TxCreator({ colony: this, + colonyNetwork: this.colonyNetwork, contract, method, args, @@ -158,6 +178,7 @@ export class Colony { ) { return new TxCreator({ colony: this, + colonyNetwork: this.colonyNetwork, contract, method, args, @@ -708,4 +729,65 @@ export class Colony { MetadataType.Annotation, ); } + + installExtension(extension: SupportedExtension) { + const Extension = supportedExtensionMap[extension]; + const version = Extension.getLatestSupportedVersion(); + const { type } = Extension; + const colonyVersion = this.colonyClient.clientVersion; + if (!isExtensionCompatible(type, version, colonyVersion)) { + throw new Error( + `v${version} of ${type} extension is not compatible with colony v${colonyVersion}`, + ); + } + return this.createTxCreator( + this.colonyClient, + 'installExtension', + [type, Extension.getLatestSupportedVersion()], + async (receipt) => ({ + ...extractEvent( + 'ExtensionInstalled', + receipt, + ), + }), + ); + } + + // TODO: consider using ColonyClient.setRoles in an improved abstraction + setAdministrationRole(address: string, teamId: BigNumberish, set: boolean) { + return this.createPermissionedTxCreator( + this.colonyClient, + 'setAdministrationRole', + [address, teamId, set], + { + roles: ColonyRole.Architecture, + domain: teamId, + }, + async (receipt) => ({ + ...extractEvent( + 'ColonyAdministrationRoleSet', + receipt, + ), + }), + ); + } + + // TODO: consider using ColonyClient.setRoles in an improved abstraction + setFundingRole(address: string, teamId: BigNumberish, set: boolean) { + return this.createPermissionedTxCreator( + this.colonyClient, + 'setFundingRole', + [address, teamId, set], + { + roles: ColonyRole.Architecture, + domain: teamId, + }, + async (receipt) => ({ + ...extractEvent( + 'ColonyFundingRoleSet', + receipt, + ), + }), + ); + } } diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index 4fbe5544..8cd30199 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -1,12 +1,16 @@ +import { BigNumberish, ContractReceipt } from 'ethers'; import { ColonyNetworkClient, getColonyNetworkClient, + IBasicMetaTransaction, Network, NetworkClientOptions, SignerOrProvider, } from '@colony/colony-js'; +import { ColonyAddedEventObject } from '@colony/colony-js/extras'; +import { ColonyMetadata } from '@colony/colony-event-metadata-parser'; -import { IpfsMetadata, IpfsAdapter } from '../ipfs'; +import { IpfsMetadata, IpfsAdapter, MetadataType } from '../ipfs'; import { Colony, SupportedExtensions } from './Colony'; import { getVotingReputationClient, @@ -14,6 +18,9 @@ import { } from './VotingReputation'; import { getOneTxPaymentClient, OneTxPayment } from './OneTxPayment'; import { MetaTxBroadCasterEndpoint } from '../constants'; +import { Parameters } from '../types'; +import { TxCreator } from './TxCreator'; +import { extractEvent } from '../utils'; /** Additional options for the [[ColonyNetwork]] */ export interface ColonyNetworkOptions { @@ -30,7 +37,7 @@ export interface ColonyNetworkConfig { } export class ColonyNetwork { - private signerOrProvider: SignerOrProvider; + config: ColonyNetworkConfig; ipfs: IpfsMetadata; @@ -38,7 +45,7 @@ export class ColonyNetwork { networkClient: ColonyNetworkClient; - config: ColonyNetworkConfig; + signerOrProvider: SignerOrProvider; /** * Creates a new instance to connect to the ColonyNetwork @@ -83,6 +90,44 @@ export class ColonyNetwork { this.signerOrProvider = signerOrProvider; } + /** + * Creates a new [[TxCreator]] ColonyNetwork transactions + * @internal + * + * @remarks + * Do not use this method directly but rather the class methods in the Colony or extensions + * + * @param contract A ColonyJS contract + * @param method The transaction method to execute on the contract + * @param args The arguments for the method + * @param eventData A function that extracts the relevant event data from the [[ContractReceipt]] + * @param metadataType The [[MetadataType]] if the event contains metadata + * @returns A [[TxCreator]] + */ + private createTxCreator< + C extends IBasicMetaTransaction, + F extends keyof C['functions'], + D extends Record, + M extends MetadataType, + >( + contract: C, + method: F, + args: + | Parameters + | (() => Promise>), + eventData?: (receipt: ContractReceipt) => Promise, + metadataType?: M, + ) { + return new TxCreator({ + colonyNetwork: this, + contract, + method, + args, + eventData, + metadataType, + }); + } + /** * Get a new instance of a Colony * @@ -97,7 +142,7 @@ export class ColonyNetwork { async getColony(address: string): Promise { const colonyClient = await this.networkClient.getColonyClient(address); - if (colonyClient.clientVersion !== Colony.SupportedVersions[0]) { + if (colonyClient.clientVersion !== Colony.supportedVersions[0]) { throw new Error( `The version of this Colony ${colonyClient.clientVersion} is not supported by Colony SDK. Please update your Colony`, ); @@ -140,4 +185,56 @@ export class ColonyNetwork { const colonyAddress = await this.networkClient.getMetaColony(); return this.getColony(colonyAddress); } + + async deployToken( + name: string, + symbol: string, + decimals = 18, + ): Promise { + // TODO: Use TxCreator + const token = await this.networkClient.deployToken(name, symbol, decimals); + const receipt = await token.wait(); + return receipt.contractAddress; + } + + async createColony(tokenAddress: string, colonyLabel: string) { + // TODO: check whether colony label is taken + return this.createTxCreator( + this.networkClient, + 'createColony(address,uint256,string)', + [tokenAddress, Colony.getLatestSupportedVersion(), colonyLabel], + async (receipt) => ({ + ...extractEvent('ColonyAdded', receipt), + }), + ); + } + + async createColonyWithMetadata( + tokenAddress: string, + colonyLabel: string, + metadata: ColonyMetadata | string, + ) { + // TODO: check whether colony label is taken + return this.createTxCreator( + this.networkClient, + 'createColony(address,uint256,string,string)', + async () => { + let cid: string; + if (typeof metadata == 'string') { + cid = metadata; + } else { + cid = await this.ipfs.uploadMetadata(MetadataType.Colony, metadata); + } + return [ + tokenAddress, + Colony.getLatestSupportedVersion(), + colonyLabel, + cid, + ] as [string, BigNumberish, string, string]; + }, + async (receipt) => ({ + ...extractEvent('ColonyAdded', receipt), + }), + ); + } } diff --git a/src/ColonyNetwork/ColonyToken.ts b/src/ColonyNetwork/ColonyToken.ts index cc04c030..eb37d7dc 100644 --- a/src/ColonyNetwork/ColonyToken.ts +++ b/src/ColonyNetwork/ColonyToken.ts @@ -19,6 +19,8 @@ export class ColonyToken { private tokenClient: ColonyTokenClient; + address: string; + tokenLockingClient: TokenLockingClient; // TODO: Add symbol, decimals @@ -41,6 +43,7 @@ export class ColonyToken { `Requested token is not a token deployed with Colony. Please use the Erc20Token class`, ); } + this.address = colonyClient.tokenClient.address; this.colony = colony; this.tokenClient = colonyClient.tokenClient; this.tokenLockingClient = tokenLockingClient; @@ -258,4 +261,34 @@ export class ColonyToken { obligator, ); } + + async deployAuthority(allowedToTransfer?: string[]): Promise { + let allowed: string[] = []; + const tokenLockingAddress = + await this.colony.colonyNetwork.networkClient.getTokenLocking(); + if (!allowedToTransfer) { + allowed = [tokenLockingAddress]; + } else { + allowed = [...allowedToTransfer, tokenLockingAddress]; + } + // TODO: Use TxCreator + const tx = await this.tokenClient.deployTokenAuthority( + this.tokenClient.address, + allowed, + ); + const receipt = await tx.wait(); + return receipt.contractAddress; + } + + async setAuthority(tokenAuthorityAddress: string) { + return this.colony.createTxCreator(this.tokenClient, 'setAuthority', [ + tokenAuthorityAddress, + ]); + } + + async setupColonyAsOwner() { + return this.colony.createTxCreator(this.tokenClient, 'setOwner', [ + this.colony.address, + ]); + } } diff --git a/src/ColonyNetwork/OneTxPayment.ts b/src/ColonyNetwork/OneTxPayment.ts index 879d744b..fe8a9f20 100644 --- a/src/ColonyNetwork/OneTxPayment.ts +++ b/src/ColonyNetwork/OneTxPayment.ts @@ -13,16 +13,19 @@ import { extractEvent } from '../utils'; import { Colony, SupportedColonyClient } from './Colony'; export type SupportedOneTxPaymentClient = OneTxPaymentClientV3; -export const SUPPORTED_ONE_TX_PAYMENT_VERSION = 3; export const getOneTxPaymentClient = async ( colonyClient: SupportedColonyClient, ) => { const oneTxPaymentClient = await colonyClient.getExtensionClient( - Extension.OneTxPayment, + OneTxPayment.type, ); - if (oneTxPaymentClient.clientVersion !== SUPPORTED_ONE_TX_PAYMENT_VERSION) { + // TODO: Support more versions? + if ( + oneTxPaymentClient.clientVersion !== + OneTxPayment.getLatestSupportedVersion() + ) { throw new Error( `The installed version ${oneTxPaymentClient.clientVersion} of the OneTxPayment extension is not supported. Please upgrade the extension in your Colony`, ); @@ -45,12 +48,22 @@ export const getOneTxPaymentClient = async ( * Note: if you deployed your Colony using the Dapp, the OneTxPayment extension is already installed for you */ export class OneTxPayment { + static supportedVersion: 3[] = [3]; + + static type: Extension.OneTxPayment; + private colony: Colony; private oneTxPaymentClient: SupportedOneTxPaymentClient; address: string; + static getLatestSupportedVersion() { + return OneTxPayment.supportedVersion[ + OneTxPayment.supportedVersion.length - 1 + ]; + } + constructor(colony: Colony, oneTxPaymentClient: SupportedOneTxPaymentClient) { this.address = oneTxPaymentClient.address; this.colony = colony; diff --git a/src/ColonyNetwork/TxCreator.ts b/src/ColonyNetwork/TxCreator.ts index c4ab11cb..1cd58a51 100644 --- a/src/ColonyNetwork/TxCreator.ts +++ b/src/ColonyNetwork/TxCreator.ts @@ -21,6 +21,7 @@ import { MetadataType, MetadataValue } from '../ipfs'; import { extractEvent } from '../utils'; import { ParsedLogTransactionReceipt } from '../types'; import { IPFS_METADATA_EVENTS } from '../ipfs/IpfsMetadata'; +import { ColonyNetwork } from './ColonyNetwork'; const { arrayify, solidityKeccak256, splitSignature } = utils; @@ -74,7 +75,9 @@ export class TxCreator< E extends EventData, MD extends MetadataType, > { - private colony: Colony; + private colonyNetwork: ColonyNetwork; + + private colony?: Colony; private contract: C; @@ -90,6 +93,7 @@ export class TxCreator< constructor({ colony, + colonyNetwork, contract, method, args, @@ -97,7 +101,8 @@ export class TxCreator< metadataType, permissionConfig, }: { - colony: Colony; + colony?: Colony; + colonyNetwork: ColonyNetwork; contract: C; method: M; args: unknown[] | (() => Promise); @@ -106,6 +111,7 @@ export class TxCreator< permissionConfig?: PermissionConfig; }) { this.colony = colony; + this.colonyNetwork = colonyNetwork; this.contract = contract; this.method = method as string; this.args = args; @@ -124,6 +130,11 @@ export class TxCreator< } if (this.permissionConfig) { + if (!this.colony) { + throw new Error( + 'Permissioned transactions can only be created on a Colony', + ); + } const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this.colony.getInternalColonyClient(), this.permissionConfig.domain, @@ -144,12 +155,11 @@ export class TxCreator< const data = await this.eventData(receipt); if (this.metadataType && data.metadata) { - const getMetadata = - this.colony.colonyNetwork.ipfs.getMetadataForEvent.bind( - this.colony.colonyNetwork.ipfs, - IPFS_METADATA_EVENTS[this.metadataType], - data.metadata, - ) as () => Promise>; + const getMetadata = this.colonyNetwork.ipfs.getMetadataForEvent.bind( + this.colonyNetwork.ipfs, + IPFS_METADATA_EVENTS[this.metadataType], + data.metadata, + ) as () => Promise>; return [data, receipt as R, getMetadata]; } @@ -161,7 +171,7 @@ export class TxCreator< } private getSigner(): Signer { - const { signerOrProvider } = this.colony; + const { signerOrProvider } = this.colonyNetwork; if (!(signerOrProvider instanceof Signer)) { throw new Error('Need a signer to create a transaction'); } @@ -172,11 +182,9 @@ export class TxCreator< encodedTransaction: string, target: string, ): Promise { - const { colonyNetwork } = this.colony; - - if (!colonyNetwork.config.metaTxBroadcasterEndpoint) { + if (!this.colonyNetwork.config.metaTxBroadcasterEndpoint) { throw new Error( - `No metatransaction broadcaster endpoint found for network ${colonyNetwork.network}`, + `No metatransaction broadcaster endpoint found for network ${this.colonyNetwork.network}`, ); } @@ -189,7 +197,7 @@ export class TxCreator< let chainId: number; - if (colonyNetwork.network === Network.Custom) { + if (this.colonyNetwork.network === Network.Custom) { chainId = 1; } else { const networkInfo = await provider.getNetwork(); @@ -219,7 +227,7 @@ export class TxCreator< }; const res = await fetch( - `${colonyNetwork.config.metaTxBroadcasterEndpoint}/broadcast`, + `${this.colonyNetwork.config.metaTxBroadcasterEndpoint}/broadcast`, { method: 'POST', headers: { @@ -280,6 +288,10 @@ export class TxCreator< * @returns A tupel of motion event data and contract receipt */ async motion(motionDomain: BigNumberish = Id.RootDomain) { + if (!this.colony) { + throw new Error('Motions can only be created on a Colony'); + } + if (!this.colony.ext.motions) { throw new Error( 'VotingReputation extension is not installed for this Colony', @@ -337,6 +349,10 @@ export class TxCreator< * @returns A tupel of motion event data and contract receipt */ async motionMeta(motionDomain: BigNumberish = Id.RootDomain) { + if (!this.colony) { + throw new Error('Motions can only be created on a Colony'); + } + if (!this.colony.ext.motions) { throw new Error( 'VotingReputation extension is not installed for this Colony', diff --git a/src/ColonyNetwork/VotingReputation.ts b/src/ColonyNetwork/VotingReputation.ts index 7fb067fd..b4189221 100644 --- a/src/ColonyNetwork/VotingReputation.ts +++ b/src/ColonyNetwork/VotingReputation.ts @@ -21,7 +21,6 @@ import { extractEvent, extractCustomEvent, toEth } from '../utils'; import { Colony, SupportedColonyClient } from './Colony'; export type SupportedVotingReputationClient = VotingReputationClientV7; -export const SUPPORTED_VOTING_REPUTATION_VERSION = 7; export type Motion = VotingReputationDataTypes.MotionStruct; @@ -38,11 +37,12 @@ export const getVotingReputationClient = async ( colonyClient: SupportedColonyClient, ) => { const votingReputationClient = await colonyClient.getExtensionClient( - Extension.VotingReputation, + VotingReputation.type, ); if ( - votingReputationClient.clientVersion !== SUPPORTED_VOTING_REPUTATION_VERSION + votingReputationClient.clientVersion !== + VotingReputation.getLatestSupportedVersion() ) { throw new Error( `The installed version ${votingReputationClient.clientVersion} of the VotingReputation extension is not supported. Please upgrade the extension in your Colony`, @@ -140,12 +140,22 @@ const REP_DIVISOR = BigNumber.from(10).pow(18); * */ export class VotingReputation { + static supportedVersions: 7[] = [7]; + + static type: Extension.IVotingReputation; + private colony: Colony; private votingReputationClient: SupportedVotingReputationClient; address: string; + static getLatestSupportedVersion() { + return VotingReputation.supportedVersions[ + VotingReputation.supportedVersions.length - 1 + ]; + } + constructor( colony: Colony, votingReputationClient: SupportedVotingReputationClient, diff --git a/src/ColonyNetwork/index.ts b/src/ColonyNetwork/index.ts index 6e0cef75..d8dd6836 100644 --- a/src/ColonyNetwork/index.ts +++ b/src/ColonyNetwork/index.ts @@ -4,7 +4,7 @@ */ export { ColonyNetwork, ColonyNetworkOptions } from './ColonyNetwork'; -export { Colony, SupportedExtensions } from './Colony'; +export { Colony, SupportedExtension, SupportedExtensions } from './Colony'; export { ColonyToken } from './ColonyToken'; export { VotingReputation, Vote } from './VotingReputation'; export { TxCreator } from './TxCreator'; From 4baa5af18ca3e8ec98cc6c90b94a44ce80eb67f4 Mon Sep 17 00:00:00 2001 From: chmanie Date: Tue, 29 Nov 2022 18:18:22 +0900 Subject: [PATCH 02/12] Use network to deploy token/authority --- docs/api/README.md | 1 + docs/api/classes/ColonyNetwork.md | 59 +++++++++----- docs/api/classes/ColonyToken.md | 4 +- docs/api/enums/ColonyLabelSuffix.md | 37 +++++++++ src/ColonyNetwork/ColonyNetwork.ts | 121 +++++++++++++++++----------- src/ColonyNetwork/ColonyToken.ts | 15 ++-- src/constants.ts | 9 +++ 7 files changed, 169 insertions(+), 77 deletions(-) create mode 100644 docs/api/enums/ColonyLabelSuffix.md diff --git a/docs/api/README.md b/docs/api/README.md index 98bc1e14..bc980302 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -6,6 +6,7 @@ ## Enumerations +- [ColonyLabelSuffix](enums/ColonyLabelSuffix.md) - [ColonyRole](enums/ColonyRole.md) - [Extension](enums/Extension.md) - [Id](enums/Id.md) diff --git a/docs/api/classes/ColonyNetwork.md b/docs/api/classes/ColonyNetwork.md index 1fb8e8fc..b4dd28b5 100644 --- a/docs/api/classes/ColonyNetwork.md +++ b/docs/api/classes/ColonyNetwork.md @@ -64,14 +64,15 @@ ___ ### createColony -▸ **createColony**(`tokenAddress`, `colonyLabel`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> +▸ **createColony**(`tokenAddress`, `label`, `metadata?`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> #### Parameters | Name | Type | | :------ | :------ | | `tokenAddress` | `string` | -| `colonyLabel` | `string` | +| `label` | `string` | +| `metadata?` | `string` \| `ColonyMetadata` | #### Returns @@ -79,27 +80,9 @@ ___ ___ -### createColonyWithMetadata - -▸ **createColonyWithMetadata**(`tokenAddress`, `colonyLabel`, `metadata`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `tokenAddress` | `string` | -| `colonyLabel` | `string` | -| `metadata` | `string` \| `ColonyMetadata` | - -#### Returns - -`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> - -___ - ### deployToken -▸ **deployToken**(`name`, `symbol`, `decimals?`): `Promise`<`string`\> +▸ **deployToken**(`name`, `symbol`, `decimals?`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> #### Parameters @@ -111,7 +94,7 @@ ___ #### Returns -`Promise`<`string`\> +`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> ___ @@ -141,6 +124,38 @@ A Colony abstaction instance ___ +### getColonyAddress + +▸ **getColonyAddress**(`label`): `Promise`<``null`` \| `string`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `label` | `string` | + +#### Returns + +`Promise`<``null`` \| `string`\> + +___ + +### getColonyLabel + +▸ **getColonyLabel**(`address`): `Promise`<``null`` \| `string`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `address` | `string` | + +#### Returns + +`Promise`<``null`` \| `string`\> + +___ + ### getMetaColony ▸ **getMetaColony**(): `Promise`<[`Colony`](Colony.md)\> diff --git a/docs/api/classes/ColonyToken.md b/docs/api/classes/ColonyToken.md index c130ed63..6df1d7c3 100644 --- a/docs/api/classes/ColonyToken.md +++ b/docs/api/classes/ColonyToken.md @@ -61,7 +61,7 @@ ___ ### deployAuthority -▸ **deployAuthority**(`allowedToTransfer?`): `Promise`<`string`\> +▸ **deployAuthority**(`allowedToTransfer?`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> #### Parameters @@ -71,7 +71,7 @@ ___ #### Returns -`Promise`<`string`\> +`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> ___ diff --git a/docs/api/enums/ColonyLabelSuffix.md b/docs/api/enums/ColonyLabelSuffix.md new file mode 100644 index 00000000..ef040b75 --- /dev/null +++ b/docs/api/enums/ColonyLabelSuffix.md @@ -0,0 +1,37 @@ +# Enumeration: ColonyLabelSuffix + +## Enumeration Members + +### Custom + +• **Custom** = ``".colony.joincolony.test"`` + +___ + +### Gnosis + +• **Gnosis** = ``".colony.joincolony.colonyxdai"`` + +___ + +### Goerli + +• **Goerli** = ``".colony.joincolony.test"`` + +___ + +### Mainnet + +• **Mainnet** = ``".colony.joincolony.eth"`` + +___ + +### Xdai + +• **Xdai** = ``".colony.joincolony.colonyxdai"`` + +___ + +### XdaiQa + +• **XdaiQa** = ``".colony.joincolony.colonyxdai"`` diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index 8cd30199..cf5ae377 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -1,4 +1,4 @@ -import { BigNumberish, ContractReceipt } from 'ethers'; +import { BigNumberish, ContractReceipt, constants, utils } from 'ethers'; import { ColonyNetworkClient, getColonyNetworkClient, @@ -7,7 +7,10 @@ import { NetworkClientOptions, SignerOrProvider, } from '@colony/colony-js'; -import { ColonyAddedEventObject } from '@colony/colony-js/extras'; +import { + ColonyAddedEventObject, + TokenDeployedEventObject, +} from '@colony/colony-js/extras'; import { ColonyMetadata } from '@colony/colony-event-metadata-parser'; import { IpfsMetadata, IpfsAdapter, MetadataType } from '../ipfs'; @@ -17,11 +20,14 @@ import { VotingReputation, } from './VotingReputation'; import { getOneTxPaymentClient, OneTxPayment } from './OneTxPayment'; -import { MetaTxBroadCasterEndpoint } from '../constants'; +import { ColonyLabelSuffix, MetaTxBroadCasterEndpoint } from '../constants'; import { Parameters } from '../types'; import { TxCreator } from './TxCreator'; import { extractEvent } from '../utils'; +const { namehash } = utils; +const { AddressZero } = constants; + /** Additional options for the [[ColonyNetwork]] */ export interface ColonyNetworkOptions { /** Provide a custom [[IpfsAdapter]] */ @@ -104,7 +110,7 @@ export class ColonyNetwork { * @param metadataType The [[MetadataType]] if the event contains metadata * @returns A [[TxCreator]] */ - private createTxCreator< + createTxCreator< C extends IBasicMetaTransaction, F extends keyof C['functions'], D extends Record, @@ -128,6 +134,52 @@ export class ColonyNetwork { }); } + async createColony( + tokenAddress: string, + label: string, + metadata?: ColonyMetadata | string, + ) { + const existingLabel = await this.getColonyAddress(label); + + if (existingLabel) { + throw new Error(`Colony label ${label} already exists!`); + } + + if (!metadata) { + return this.createTxCreator( + this.networkClient, + 'createColony(address,uint256,string)', + [tokenAddress, Colony.getLatestSupportedVersion(), label], + async (receipt) => ({ + ...extractEvent('ColonyAdded', receipt), + }), + ); + } + + return this.createTxCreator( + this.networkClient, + 'createColony(address,uint256,string,string)', + async () => { + let cid: string; + if (typeof metadata == 'string') { + cid = metadata; + } else { + cid = await this.ipfs.uploadMetadata(MetadataType.Colony, metadata); + } + return [ + tokenAddress, + Colony.getLatestSupportedVersion(), + label, + cid, + ] as [string, BigNumberish, string, string]; + }, + async (receipt) => ({ + ...extractEvent('ColonyAdded', receipt), + }), + MetadataType.Colony, + ); + } + /** * Get a new instance of a Colony * @@ -186,54 +238,33 @@ export class ColonyNetwork { return this.getColony(colonyAddress); } - async deployToken( - name: string, - symbol: string, - decimals = 18, - ): Promise { - // TODO: Use TxCreator - const token = await this.networkClient.deployToken(name, symbol, decimals); - const receipt = await token.wait(); - return receipt.contractAddress; + async getColonyLabel(address: string) { + const ensName = + await this.networkClient.lookupRegisteredENSDomainWithNetworkPatches( + address, + ); + if (ensName) { + return ensName.replace(ColonyLabelSuffix[this.network], ''); + } + return null; } - async createColony(tokenAddress: string, colonyLabel: string) { - // TODO: check whether colony label is taken - return this.createTxCreator( - this.networkClient, - 'createColony(address,uint256,string)', - [tokenAddress, Colony.getLatestSupportedVersion(), colonyLabel], - async (receipt) => ({ - ...extractEvent('ColonyAdded', receipt), - }), - ); + async getColonyAddress(label: string) { + const hash = namehash(`${label}${ColonyLabelSuffix[this.network]}`); + const address = await this.networkClient.addr(hash); + if (address !== AddressZero) { + return address; + } + return null; } - async createColonyWithMetadata( - tokenAddress: string, - colonyLabel: string, - metadata: ColonyMetadata | string, - ) { - // TODO: check whether colony label is taken + async deployToken(name: string, symbol: string, decimals = 18) { return this.createTxCreator( this.networkClient, - 'createColony(address,uint256,string,string)', - async () => { - let cid: string; - if (typeof metadata == 'string') { - cid = metadata; - } else { - cid = await this.ipfs.uploadMetadata(MetadataType.Colony, metadata); - } - return [ - tokenAddress, - Colony.getLatestSupportedVersion(), - colonyLabel, - cid, - ] as [string, BigNumberish, string, string]; - }, + 'deployTokenViaNetwork', + [name, symbol, decimals], async (receipt) => ({ - ...extractEvent('ColonyAdded', receipt), + ...extractEvent('TokenDeployed', receipt), }), ); } diff --git a/src/ColonyNetwork/ColonyToken.ts b/src/ColonyNetwork/ColonyToken.ts index eb37d7dc..30bfa708 100644 --- a/src/ColonyNetwork/ColonyToken.ts +++ b/src/ColonyNetwork/ColonyToken.ts @@ -262,22 +262,21 @@ export class ColonyToken { ); } - async deployAuthority(allowedToTransfer?: string[]): Promise { + async deployAuthority(allowedToTransfer?: string[]) { + const { colonyNetwork } = this.colony; let allowed: string[] = []; const tokenLockingAddress = - await this.colony.colonyNetwork.networkClient.getTokenLocking(); + await colonyNetwork.networkClient.getTokenLocking(); if (!allowedToTransfer) { allowed = [tokenLockingAddress]; } else { allowed = [...allowedToTransfer, tokenLockingAddress]; } - // TODO: Use TxCreator - const tx = await this.tokenClient.deployTokenAuthority( - this.tokenClient.address, - allowed, + return colonyNetwork.createTxCreator( + colonyNetwork.networkClient, + 'deployTokenAuthority', + [this.address, this.colony.address, allowed], ); - const receipt = await tx.wait(); - return receipt.contractAddress; } async setAuthority(tokenAuthorityAddress: string) { diff --git a/src/constants.ts b/src/constants.ts index da608016..af38539b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -34,3 +34,12 @@ export enum TeamColor { Magenta, PurpleGrey, } + +export enum ColonyLabelSuffix { + Mainnet = '.colony.joincolony.eth', + Goerli = '.colony.joincolony.test', + Gnosis = '.colony.joincolony.colonyxdai', + Xdai = '.colony.joincolony.colonyxdai', + XdaiQa = '.colony.joincolony.colonyxdai', + Custom = '.colony.joincolony.test', +} From 667f9194091f4aac5f81c1fa940886594efb55f4 Mon Sep 17 00:00:00 2001 From: chmanie Date: Wed, 30 Nov 2022 16:27:26 +0900 Subject: [PATCH 03/12] Use overloads for createColony() --- docs/api/classes/ColonyNetwork.md | 23 +++++++++++++++----- src/ColonyNetwork/ColonyNetwork.ts | 34 ++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/docs/api/classes/ColonyNetwork.md b/docs/api/classes/ColonyNetwork.md index b4dd28b5..69de89a2 100644 --- a/docs/api/classes/ColonyNetwork.md +++ b/docs/api/classes/ColonyNetwork.md @@ -64,7 +64,7 @@ ___ ### createColony -▸ **createColony**(`tokenAddress`, `label`, `metadata?`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> +▸ **createColony**(`tokenAddress`, `label`, `metadata`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\> #### Parameters @@ -72,17 +72,30 @@ ___ | :------ | :------ | | `tokenAddress` | `string` | | `label` | `string` | -| `metadata?` | `string` \| `ColonyMetadata` | +| `metadata` | `string` \| `ColonyMetadata` | #### Returns -`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress?`: `string` ; `colonyId?`: `BigNumber` ; `token?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> +[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\> + +▸ **createColony**(`tokenAddress`, `label`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `tokenAddress` | `string` | +| `label` | `string` | + +#### Returns + +[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ ### deployToken -▸ **deployToken**(`name`, `symbol`, `decimals?`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> +▸ **deployToken**(`name`, `symbol`, `decimals?`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters @@ -94,7 +107,7 @@ ___ #### Returns -`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\>\> +[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index cf5ae377..68fb8531 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -9,6 +9,7 @@ import { } from '@colony/colony-js'; import { ColonyAddedEventObject, + ColonyMetadataEventObject, TokenDeployedEventObject, } from '@colony/colony-js/extras'; import { ColonyMetadata } from '@colony/colony-event-metadata-parser'; @@ -21,7 +22,7 @@ import { } from './VotingReputation'; import { getOneTxPaymentClient, OneTxPayment } from './OneTxPayment'; import { ColonyLabelSuffix, MetaTxBroadCasterEndpoint } from '../constants'; -import { Parameters } from '../types'; +import { Expand, Parameters } from '../types'; import { TxCreator } from './TxCreator'; import { extractEvent } from '../utils'; @@ -134,17 +135,32 @@ export class ColonyNetwork { }); } - async createColony( + createColony( tokenAddress: string, label: string, - metadata?: ColonyMetadata | string, - ) { - const existingLabel = await this.getColonyAddress(label); + metadata: ColonyMetadata | string, + ): TxCreator< + ColonyNetworkClient, + 'createColony(address,uint256,string,string)', + Expand, + MetadataType.Colony + >; - if (existingLabel) { - throw new Error(`Colony label ${label} already exists!`); - } + createColony( + tokenAddress: string, + label: string, + ): TxCreator< + ColonyNetworkClient, + 'createColony(address,uint256,string)', + Expand, + MetadataType + >; + createColony( + tokenAddress: string, + label: string, + metadata?: ColonyMetadata | string, + ) { if (!metadata) { return this.createTxCreator( this.networkClient, @@ -258,7 +274,7 @@ export class ColonyNetwork { return null; } - async deployToken(name: string, symbol: string, decimals = 18) { + deployToken(name: string, symbol: string, decimals = 18) { return this.createTxCreator( this.networkClient, 'deployTokenViaNetwork', From cd8abc56f4c1fcac7e48f126ae46b2d6092ce24a Mon Sep 17 00:00:00 2001 From: chmanie Date: Thu, 1 Dec 2022 22:18:33 +0900 Subject: [PATCH 04/12] Update colony-events-metadata-parser to v2-beta.1 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ea9a6a9c..ee7d52c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.7.0", "license": "GPL-3.0-only", "dependencies": { - "@colony/colony-event-metadata-parser": "^2.0.0-beta.0", + "@colony/colony-event-metadata-parser": "^2.0.0-beta.1", "@colony/colony-js": "^6.0.2", "@urql/core": "^2.5.0", "cross-fetch": "^3.1.5", @@ -174,9 +174,9 @@ } }, "node_modules/@colony/colony-event-metadata-parser": { - "version": "2.0.0-beta.0", - "resolved": "https://registry.npmjs.org/@colony/colony-event-metadata-parser/-/colony-event-metadata-parser-2.0.0-beta.0.tgz", - "integrity": "sha512-AnXYKH91VDz1u8jng7ulNeigbliTmV9YLgzhXVowNcUBB4EdolQ45IihCoBOURSblISVYjVB/IiB2mIG0Bj8dA==", + "version": "2.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@colony/colony-event-metadata-parser/-/colony-event-metadata-parser-2.0.0-beta.1.tgz", + "integrity": "sha512-LVp2MFzu5dUFuAmdX11bZw0ZTOtZK/rB/gaL/kbzR1d4CO9ctBmgQQti95etre4SWl7M79Eesn8sGk9sAWPFkw==", "dependencies": { "lint-staged": "^13.0.3", "react-intl": "^6.0.4", @@ -8206,9 +8206,9 @@ } }, "@colony/colony-event-metadata-parser": { - "version": "2.0.0-beta.0", - "resolved": "https://registry.npmjs.org/@colony/colony-event-metadata-parser/-/colony-event-metadata-parser-2.0.0-beta.0.tgz", - "integrity": "sha512-AnXYKH91VDz1u8jng7ulNeigbliTmV9YLgzhXVowNcUBB4EdolQ45IihCoBOURSblISVYjVB/IiB2mIG0Bj8dA==", + "version": "2.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@colony/colony-event-metadata-parser/-/colony-event-metadata-parser-2.0.0-beta.1.tgz", + "integrity": "sha512-LVp2MFzu5dUFuAmdX11bZw0ZTOtZK/rB/gaL/kbzR1d4CO9ctBmgQQti95etre4SWl7M79Eesn8sGk9sAWPFkw==", "requires": { "lint-staged": "^13.0.3", "react-intl": "^6.0.4", diff --git a/package.json b/package.json index 5073a127..cf8ec3d6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.7.0", "license": "GPL-3.0-only", "dependencies": { - "@colony/colony-event-metadata-parser": "^2.0.0-beta.0", + "@colony/colony-event-metadata-parser": "^2.0.0-beta.1", "@colony/colony-js": "^6.0.2", "@urql/core": "^2.5.0", "cross-fetch": "^3.1.5", From 3af0416307ff747c072c21cfa8f3e68edbae3aef Mon Sep 17 00:00:00 2001 From: chmanie Date: Thu, 1 Dec 2022 22:19:28 +0900 Subject: [PATCH 05/12] Bugfixes for colony creation functions --- docs/api/classes/Colony.md | 8 ++--- docs/api/classes/ColonyToken.md | 12 +++---- docs/api/classes/TxCreator.md | 8 ++--- docs/api/classes/VotingReputation.md | 8 ++--- docs/api/interfaces/ColonyEvent.md | 6 ++-- src/ColonyNetwork/Colony.ts | 30 +++++++++-------- src/ColonyNetwork/ColonyNetwork.ts | 22 ++++++++++--- src/ColonyNetwork/ColonyToken.ts | 47 ++++++++++++++++++++------- src/ColonyNetwork/OneTxPayment.ts | 4 +-- src/ColonyNetwork/VotingReputation.ts | 5 +-- 10 files changed, 95 insertions(+), 55 deletions(-) diff --git a/docs/api/classes/Colony.md b/docs/api/classes/Colony.md index 09b193e7..973666c3 100644 --- a/docs/api/classes/Colony.md +++ b/docs/api/classes/Colony.md @@ -484,7 +484,7 @@ ___ ### setAdministrationRole -▸ **setAdministrationRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +▸ **setAdministrationRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters @@ -496,13 +496,13 @@ ___ #### Returns -[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ ### setFundingRole -▸ **setFundingRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +▸ **setFundingRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters @@ -514,7 +514,7 @@ ___ #### Returns -[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ diff --git a/docs/api/classes/ColonyToken.md b/docs/api/classes/ColonyToken.md index 6df1d7c3..500a7cc1 100644 --- a/docs/api/classes/ColonyToken.md +++ b/docs/api/classes/ColonyToken.md @@ -61,7 +61,7 @@ ___ ### deployAuthority -▸ **deployAuthority**(`allowedToTransfer?`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> +▸ **deployAuthority**(`allowedToTransfer?`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenAuthority"``, { `tokenAuthorityAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters @@ -71,7 +71,7 @@ ___ #### Returns -`Promise`<[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> +[`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenAuthority"``, { `tokenAuthorityAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ @@ -208,7 +208,7 @@ ___ ### setAuthority -▸ **setAuthority**(`tokenAuthorityAddress`): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> +▸ **setAuthority**(`tokenAuthorityAddress`): [`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters @@ -218,17 +218,17 @@ ___ #### Returns -`Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> +[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setAuthority"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\> ___ ### setupColonyAsOwner -▸ **setupColonyAsOwner**(): `Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setOwner"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> +▸ **setupColonyAsOwner**(): [`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setOwner"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\> #### Returns -`Promise`<[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setOwner"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\>\> +[`TxCreator`](TxCreator.md)<`ColonyTokenClient`, ``"setOwner"``, `Record`<`string`, `unknown`\>, [`MetadataType`](../enums/MetadataType.md)\> ___ diff --git a/docs/api/classes/TxCreator.md b/docs/api/classes/TxCreator.md index 2c521100..5c758445 100644 --- a/docs/api/classes/TxCreator.md +++ b/docs/api/classes/TxCreator.md @@ -58,7 +58,7 @@ Learn more about these functions in their individual documentation ### force -▸ **force**(): `Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> +▸ **force**(): `Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> Forces an action @@ -68,7 +68,7 @@ The user sending this transaction has to have the appropriate permissions to do #### Returns -`Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> +`Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> A tupel of event data and contract receipt (and a function to retrieve metadata if applicable) @@ -76,7 +76,7 @@ ___ ### forceMeta -▸ **forceMeta**(): `Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> +▸ **forceMeta**(): `Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> Forces an action using a gasless metatransaction @@ -86,7 +86,7 @@ The user sending this transaction has to have the appropriate permissions to do #### Returns -`Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> +`Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> A tupel of event data and contract receipt (and a function to retrieve metadata if applicable) diff --git a/docs/api/classes/VotingReputation.md b/docs/api/classes/VotingReputation.md index 13099a62..58a1876c 100644 --- a/docs/api/classes/VotingReputation.md +++ b/docs/api/classes/VotingReputation.md @@ -104,15 +104,15 @@ You can - at any point in the lifecycle inspect the current state of a Motion. U ___ -### supportedVersions +### extensionType -▪ `Static` **supportedVersions**: ``7``[] +▪ `Static` **extensionType**: [`IVotingReputation`](../enums/Extension.md#ivotingreputation) = `Extension.IVotingReputation` ___ -### type +### supportedVersions -▪ `Static` **type**: [`IVotingReputation`](../enums/Extension.md#ivotingreputation) +▪ `Static` **supportedVersions**: ``7``[] ## Methods diff --git a/docs/api/interfaces/ColonyEvent.md b/docs/api/interfaces/ColonyEvent.md index 69a1e0a6..b9b8ed6c 100644 --- a/docs/api/interfaces/ColonyEvent.md +++ b/docs/api/interfaces/ColonyEvent.md @@ -68,15 +68,15 @@ ___ ### getMetadata -• `Optional` **getMetadata**: () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> +• `Optional` **getMetadata**: () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> #### Type declaration -▸ (): `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> +▸ (): `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> ##### Returns -`Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `undefined` \| `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `undefined` \| `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `undefined` \| `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `undefined` \| `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `undefined` \| `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> +`Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> ___ diff --git a/src/ColonyNetwork/Colony.ts b/src/ColonyNetwork/Colony.ts index 1b71c59e..15491e96 100644 --- a/src/ColonyNetwork/Colony.ts +++ b/src/ColonyNetwork/Colony.ts @@ -7,15 +7,15 @@ import { getChildIndex, getPermissionProofs, isExtensionCompatible, + getExtensionHash, } from '@colony/colony-js'; import { AnnotationEventObject, - ColonyAdministrationRoleSetEventObject, ColonyDataTypes, - ColonyFundingRoleSetEventObject, ColonyFundsClaimed_address_uint256_uint256_EventObject, // eslint-disable-next-line max-len ColonyFundsMovedBetweenFundingPots_address_uint256_uint256_uint256_address_EventObject, + ColonyRoleSet_address_address_uint256_uint8_bool_EventObject, DomainAdded_uint256_EventObject, DomainDeprecatedEventObject, DomainMetadataEventObject, @@ -29,12 +29,13 @@ import { } from '@colony/colony-event-metadata-parser'; import { BigNumberish, BytesLike, ContractReceipt } from 'ethers'; -import { extractEvent } from '../utils'; +import type { Expand, Parameters, ParametersFrom2 } from '../types'; + +import { extractEvent, extractCustomEvent } from '../utils'; import { ColonyToken } from './ColonyToken'; import { ColonyNetwork } from './ColonyNetwork'; import { OneTxPayment } from './OneTxPayment'; import { VotingReputation } from './VotingReputation'; -import { Expand, Parameters, ParametersFrom2 } from '../types'; import { PermissionConfig, TxCreator } from './TxCreator'; export type SupportedColonyClient = ColonyClientV10; @@ -733,21 +734,22 @@ export class Colony { installExtension(extension: SupportedExtension) { const Extension = supportedExtensionMap[extension]; const version = Extension.getLatestSupportedVersion(); - const { type } = Extension; + const { extensionType } = Extension; const colonyVersion = this.colonyClient.clientVersion; - if (!isExtensionCompatible(type, version, colonyVersion)) { + if (!isExtensionCompatible(extensionType, version, colonyVersion)) { throw new Error( - `v${version} of ${type} extension is not compatible with colony v${colonyVersion}`, + `v${version} of ${extensionType} extension is not compatible with colony v${colonyVersion}`, ); } return this.createTxCreator( this.colonyClient, 'installExtension', - [type, Extension.getLatestSupportedVersion()], + [getExtensionHash(extensionType), Extension.getLatestSupportedVersion()], async (receipt) => ({ - ...extractEvent( + ...extractCustomEvent( 'ExtensionInstalled', receipt, + this.colonyNetwork.networkClient.interface, ), }), ); @@ -764,8 +766,9 @@ export class Colony { domain: teamId, }, async (receipt) => ({ - ...extractEvent( - 'ColonyAdministrationRoleSet', + // eslint-disable-next-line max-len + ...extractEvent( + 'ColonyRoleSet', receipt, ), }), @@ -783,8 +786,9 @@ export class Colony { domain: teamId, }, async (receipt) => ({ - ...extractEvent( - 'ColonyFundingRoleSet', + // eslint-disable-next-line max-len + ...extractEvent( + 'ColonyRoleSet', receipt, ), }), diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index 68fb8531..9c4278bd 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -161,11 +161,24 @@ export class ColonyNetwork { label: string, metadata?: ColonyMetadata | string, ) { + const checkLabel = async () => { + const existingLabel = await this.getColonyAddress(label); + + if (existingLabel) { + throw new Error(`Colony label ${label} already exists`); + } + return [tokenAddress, Colony.getLatestSupportedVersion(), label] as [ + string, + BigNumberish, + string, + ]; + }; + if (!metadata) { return this.createTxCreator( this.networkClient, 'createColony(address,uint256,string)', - [tokenAddress, Colony.getLatestSupportedVersion(), label], + checkLabel, async (receipt) => ({ ...extractEvent('ColonyAdded', receipt), }), @@ -176,6 +189,8 @@ export class ColonyNetwork { this.networkClient, 'createColony(address,uint256,string,string)', async () => { + await checkLabel(); + let cid: string; if (typeof metadata == 'string') { cid = metadata; @@ -255,10 +270,7 @@ export class ColonyNetwork { } async getColonyLabel(address: string) { - const ensName = - await this.networkClient.lookupRegisteredENSDomainWithNetworkPatches( - address, - ); + const ensName = await this.networkClient.lookupRegisteredENSDomain(address); if (ensName) { return ensName.replace(ColonyLabelSuffix[this.network], ''); } diff --git a/src/ColonyNetwork/ColonyToken.ts b/src/ColonyNetwork/ColonyToken.ts index 30bfa708..7893923e 100644 --- a/src/ColonyNetwork/ColonyToken.ts +++ b/src/ColonyNetwork/ColonyToken.ts @@ -5,6 +5,7 @@ import { } from '@colony/colony-js'; import { ApprovalEventObject, + TokenAuthorityDeployedEventObject, UserTokenDepositedEventObject, UserTokenWithdrawnEventObject, } from '@colony/colony-js/extras'; @@ -49,6 +50,16 @@ export class ColonyToken { this.tokenLockingClient = tokenLockingClient; } + /** + * Provide direct access to the internally used ColonyJS TokenClient client. Only use when you know what you're doing + * @internal + * + * @returns The internally used TokenClient + */ + getInternalTokenClient(): ColonyTokenClient { + return this.tokenClient; + } + /** * Gets the token's symbol * @@ -262,30 +273,42 @@ export class ColonyToken { ); } - async deployAuthority(allowedToTransfer?: string[]) { + deployAuthority(allowedToTransfer?: string[]) { const { colonyNetwork } = this.colony; - let allowed: string[] = []; - const tokenLockingAddress = - await colonyNetwork.networkClient.getTokenLocking(); - if (!allowedToTransfer) { - allowed = [tokenLockingAddress]; - } else { - allowed = [...allowedToTransfer, tokenLockingAddress]; - } return colonyNetwork.createTxCreator( colonyNetwork.networkClient, 'deployTokenAuthority', - [this.address, this.colony.address, allowed], + async () => { + let allowed: string[] = []; + const tokenLockingAddress = + await colonyNetwork.networkClient.getTokenLocking(); + if (!allowedToTransfer) { + allowed = [tokenLockingAddress]; + } else { + allowed = [...allowedToTransfer, tokenLockingAddress]; + } + return [this.address, this.colony.address, allowed] as [ + string, + string, + string[], + ]; + }, + async (receipt) => ({ + ...extractEvent( + 'TokenAuthorityDeployed', + receipt, + ), + }), ); } - async setAuthority(tokenAuthorityAddress: string) { + setAuthority(tokenAuthorityAddress: string) { return this.colony.createTxCreator(this.tokenClient, 'setAuthority', [ tokenAuthorityAddress, ]); } - async setupColonyAsOwner() { + setupColonyAsOwner() { return this.colony.createTxCreator(this.tokenClient, 'setOwner', [ this.colony.address, ]); diff --git a/src/ColonyNetwork/OneTxPayment.ts b/src/ColonyNetwork/OneTxPayment.ts index fe8a9f20..bfc004db 100644 --- a/src/ColonyNetwork/OneTxPayment.ts +++ b/src/ColonyNetwork/OneTxPayment.ts @@ -18,7 +18,7 @@ export const getOneTxPaymentClient = async ( colonyClient: SupportedColonyClient, ) => { const oneTxPaymentClient = await colonyClient.getExtensionClient( - OneTxPayment.type, + OneTxPayment.extensionType, ); // TODO: Support more versions? @@ -50,7 +50,7 @@ export const getOneTxPaymentClient = async ( export class OneTxPayment { static supportedVersion: 3[] = [3]; - static type: Extension.OneTxPayment; + static extensionType: Extension.OneTxPayment = Extension.OneTxPayment; private colony: Colony; diff --git a/src/ColonyNetwork/VotingReputation.ts b/src/ColonyNetwork/VotingReputation.ts index b4189221..b56f7adf 100644 --- a/src/ColonyNetwork/VotingReputation.ts +++ b/src/ColonyNetwork/VotingReputation.ts @@ -37,7 +37,7 @@ export const getVotingReputationClient = async ( colonyClient: SupportedColonyClient, ) => { const votingReputationClient = await colonyClient.getExtensionClient( - VotingReputation.type, + VotingReputation.extensionType, ); if ( @@ -142,7 +142,8 @@ const REP_DIVISOR = BigNumber.from(10).pow(18); export class VotingReputation { static supportedVersions: 7[] = [7]; - static type: Extension.IVotingReputation; + static extensionType: Extension.IVotingReputation = + Extension.IVotingReputation; private colony: Colony; From a1e63c6766eec4d0381f0a7029aca6f2ed45d65e Mon Sep 17 00:00:00 2001 From: chmanie Date: Thu, 1 Dec 2022 22:34:02 +0900 Subject: [PATCH 06/12] Finish complete colony creation example --- examples/node/create.ts | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 examples/node/create.ts diff --git a/examples/node/create.ts b/examples/node/create.ts new file mode 100644 index 00000000..3f1fa14b --- /dev/null +++ b/examples/node/create.ts @@ -0,0 +1,76 @@ +import { providers, Wallet } from 'ethers'; + +import { ColonyNetwork, ColonyRole, Id, SupportedExtension } from '../../src'; + +const provider = new providers.JsonRpcProvider('https://xdai.colony.io/rpc2/'); + +// Deploy a Colony with everything that's needed +const start = async () => { + const signer = new Wallet(process.env.PRIVATE_KEY as string).connect( + provider, + ); + const colonyNetwork = new ColonyNetwork(signer); + // Create token to be used with Colony + const [{ tokenAddress }] = await colonyNetwork + .deployToken('Test token', 'TOT') + .force(); + console.info('Token address', tokenAddress); + if (!tokenAddress) { + return; + } + // Create actual colony (deploys Colony contract) + const [{ colonyAddress }] = await colonyNetwork + .createColony(tokenAddress, 'createcolonytest3') + .force(); + if (!colonyAddress) { + return; + } + console.info('Colony address', colonyAddress); + // Instantiate colony and token + let colony = await colonyNetwork.getColony(colonyAddress); + const token = await colony.getToken(); + // Deploy TokanAuthority + const [{ tokenAuthorityAddress }] = await token + .deployAuthority([colonyAddress]) + .force(); + if (!tokenAuthorityAddress) { + return; + } + console.info('Token authority address', tokenAuthorityAddress); + // Set the token's authority to the freshly deployed one + await token.setAuthority(tokenAuthorityAddress).force(); + // Install OneTxPayment extension + const [{ extensionId, version }] = await colony + .installExtension(SupportedExtension.oneTx) + .force(); + if (!extensionId || !version) { + return; + } + console.info('ExtensionId', extensionId); + console.info('Extension version', version); + // Intantiate Colony again to update the extensions + colony = await colonyNetwork.getColony(colonyAddress); + if (!colony.ext.oneTx) { + console.error('Could not instantiate OneTx extension within Colony'); + return; + } + // Give Administration role to OneTxPayment extension + const [{ user, setTo, role }] = await colony + .setAdministrationRole(colony.ext.oneTx.address, Id.RootDomain, true) + .force(); + if (!role) { + return; + } + console.info(user, setTo, ColonyRole[role]); + // Give Funding role to OneTxPayment extension + const [{ user: fundingUser, setTo: fundingSetTo, role: fundingRole }] = + await colony + .setFundingRole(colony.ext.oneTx.address, Id.RootDomain, true) + .force(); + if (!fundingRole) { + return; + } + console.info(fundingUser, fundingSetTo, ColonyRole[fundingRole]); +}; + +start(); From 125b0e67f38b35e9df962c3a95e2076536f33423 Mon Sep 17 00:00:00 2001 From: chmanie Date: Mon, 5 Dec 2022 17:20:26 +0900 Subject: [PATCH 07/12] Add docs to ColonyNetwork colony creation methods --- docs/api/README.md | 3 + docs/api/classes/Colony.md | 2 +- docs/api/classes/ColonyNetwork.md | 117 ++++++++++++++++++++- docs/api/classes/OneTxPayment.md | 107 +++++++++++++++++++ docs/api/classes/TxCreator.md | 8 +- docs/api/interfaces/ColonyEvent.md | 6 +- docs/api/interfaces/ColonyMetadata.md | 43 ++++++++ docs/api/interfaces/DomainMetadata.md | 19 ++++ docs/api/interfaces/SupportedExtensions.md | 2 +- src/ColonyNetwork/ColonyNetwork.ts | 116 +++++++++++++++++++- src/ColonyNetwork/TxCreator.ts | 3 +- src/ColonyNetwork/index.ts | 1 + src/events/ColonyEventManager.ts | 3 +- src/index.ts | 8 +- src/ipfs/IpfsMetadata.ts | 2 - src/ipfs/index.ts | 7 +- 16 files changed, 419 insertions(+), 28 deletions(-) create mode 100644 docs/api/classes/OneTxPayment.md create mode 100644 docs/api/interfaces/ColonyMetadata.md create mode 100644 docs/api/interfaces/DomainMetadata.md diff --git a/docs/api/README.md b/docs/api/README.md index bc980302..64dc9caf 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -25,6 +25,7 @@ - [ColonyEventManager](classes/ColonyEventManager.md) - [ColonyNetwork](classes/ColonyNetwork.md) - [ColonyToken](classes/ColonyToken.md) +- [OneTxPayment](classes/OneTxPayment.md) - [PinataAdapter](classes/PinataAdapter.md) - [TxCreator](classes/TxCreator.md) - [VotingReputation](classes/VotingReputation.md) @@ -35,9 +36,11 @@ - [ColonyEvent](interfaces/ColonyEvent.md) - [ColonyEventManagerOptions](interfaces/ColonyEventManagerOptions.md) - [ColonyFilter](interfaces/ColonyFilter.md) +- [ColonyMetadata](interfaces/ColonyMetadata.md) - [ColonyMultiFilter](interfaces/ColonyMultiFilter.md) - [ColonyNetworkOptions](interfaces/ColonyNetworkOptions.md) - [ColonyTopic](interfaces/ColonyTopic.md) +- [DomainMetadata](interfaces/DomainMetadata.md) - [Ethers6Filter](interfaces/Ethers6Filter.md) - [Ethers6FilterByBlockHash](interfaces/Ethers6FilterByBlockHash.md) - [EventSources](interfaces/EventSources.md) diff --git a/docs/api/classes/Colony.md b/docs/api/classes/Colony.md index 973666c3..e50f1736 100644 --- a/docs/api/classes/Colony.md +++ b/docs/api/classes/Colony.md @@ -173,7 +173,7 @@ import { TeamColor } from '@colony/sdk'; | Name | Type | Description | | :------ | :------ | :------ | -| `metadata` | `string` \| `DomainMetadata` | The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If DomainMetadata 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. | +| `metadata` | `string` \| [`DomainMetadata`](../interfaces/DomainMetadata.md) | The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [DomainMetadata](../interfaces/DomainMetadata.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 diff --git a/docs/api/classes/ColonyNetwork.md b/docs/api/classes/ColonyNetwork.md index 69de89a2..df5f3500 100644 --- a/docs/api/classes/ColonyNetwork.md +++ b/docs/api/classes/ColonyNetwork.md @@ -66,20 +66,91 @@ ___ ▸ **createColony**(`tokenAddress`, `label`, `metadata`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `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 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). + +**`Example`** + +```typescript +import { Tokens } from '@colony/sdk'; + +// Immediately executing async function +(async function() { + // Create a colony with some metadata details attached + // (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', { + 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], + }).force(); +})(); +``` + #### Parameters -| Name | Type | -| :------ | :------ | -| `tokenAddress` | `string` | -| `label` | `string` | -| `metadata` | `string` \| `ColonyMetadata` | +| Name | Type | Description | +| :------ | :------ | :------ | +| `tokenAddress` | `string` | - | +| `label` | `string` | - | +| `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 [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string,string)"``, { `agent`: `string` ; `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata`: `string` ; `token`: `string` }, [`Colony`](../enums/MetadataType.md#colony)\> +A [TxCreator](TxCreator.md) + +**Event data** + +| Property | Type | Description | +| :------ | :------ | :------ | +| `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 | +| `metadata` | string | IPFS CID of metadata attached to this transaction | + +**Metadata** (can be obtained by calling and awaiting the `getMetadata` function) + +| Property | Type | Description | +| :------ | :------ | :------ | +| `colonyDisplayName` | string | The name that should be displayed for the colony | +| `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`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `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 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). + +**`Example`** + +```typescript +// Immediately executing async function +(async function() { + // Create a colony + // (forced transaction example) + await colonyNetwork + // Use USDC on Gnosis chain as the native token + .createColony('0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83') + .force(); +})(); +``` + #### Parameters | Name | Type | @@ -91,12 +162,32 @@ ___ [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"createColony(address,uint256,string)"``, { `colonyAddress`: `string` ; `colonyId`: `BigNumber` ; `metadata?`: `undefined` ; `token`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +A [TxCreator](TxCreator.md) + +**Event data** + +| Property | Type | Description | +| :------ | :------ | :------ | +| `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 | + ___ ### deployToken ▸ **deployToken**(`name`, `symbol`, `decimals?`): [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +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). + +**`Remarks`** + +The token deployed with this function is locked by default. Call `unlockToken()` on the Colony at a later point to unlock it. + #### Parameters | Name | Type | Default value | @@ -109,6 +200,8 @@ ___ [`TxCreator`](TxCreator.md)<`ColonyNetworkClient`, ``"deployTokenViaNetwork"``, { `tokenAddress?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +The colony's address + ___ ### getColony @@ -141,6 +234,11 @@ ___ ▸ **getColonyAddress**(`label`): `Promise`<``null`` \| `string`\> +Get the colony's addess by the ENS label + +Returns the colony's address that belongs to the given ENS label +Will return `null` if the given label was not assigned to a colony. + #### Parameters | Name | Type | @@ -151,12 +249,19 @@ ___ `Promise`<``null`` \| `string`\> +The colony's address + ___ ### getColonyLabel ▸ **getColonyLabel**(`address`): `Promise`<``null`` \| `string`\> +Get the colony's ENS label + +Returns the colony's ENS label, just like it's shown in the browsers address bar after `/colony/`, when using the dApp. +Will return `null` if the colony does not exist or if no label was assigned yet + #### Parameters | Name | Type | @@ -167,6 +272,8 @@ ___ `Promise`<``null`` \| `string`\> +The colony's ENS label + ___ ### getMetaColony diff --git a/docs/api/classes/OneTxPayment.md b/docs/api/classes/OneTxPayment.md new file mode 100644 index 00000000..cf6f9a0f --- /dev/null +++ b/docs/api/classes/OneTxPayment.md @@ -0,0 +1,107 @@ +# Class: OneTxPayment + +## `OneTxPayment` (One Transaction Payment) + +Ordinarily payments require more than one transaction, because the payment lifecycle requires more than one permissioned role. + +In some use cases, there might be a need for one authorized individual to be able to create, funds, and finalize a payment within a single transaction. + +The OneTxPayment extension adds this functionality by adding a makePayment function which requires the caller to have both Funding and administration ability within the domain of the payment. + +Extension therefore requires Administration and Funding roles to function. + +Note: if you deployed your Colony using the Dapp, the OneTxPayment extension is already installed for you + +## Constructors + +### constructor + +• **new OneTxPayment**(`colony`, `oneTxPaymentClient`) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `colony` | [`Colony`](Colony.md) | +| `oneTxPaymentClient` | `OneTxPaymentClientV3` | + +## Properties + +### address + +• **address**: `string` + +___ + +### extensionType + +▪ `Static` **extensionType**: [`OneTxPayment`](../enums/Extension.md#onetxpayment) = `Extension.OneTxPayment` + +___ + +### supportedVersion + +▪ `Static` **supportedVersion**: ``3``[] + +## Methods + +### pay + +▸ **pay**(`recipient`, `amount`, `teamId?`, `tokenAddress?`): [`TxCreator`](TxCreator.md)<`OneTxPaymentClientV3`, ``"makePaymentFundedFromDomain"``, { `agent?`: `string` ; `fundamentalId?`: `BigNumber` ; `nPayouts?`: `BigNumber` }, [`MetadataType`](../enums/MetadataType.md)\> + +Make a payment to a single address using a single token + +**`Remarks`** + +Requires the `OneTxPayment` extension to be installed for the Colony (this is usually the case for Colonies created via the Dapp). Note that most tokens use 18 decimals, so add a bunch of zeros or use our `w` or `toWei` functions (see example) + +**`Example`** + +```typescript +import { Id, Tokens, w } from '@colony/sdk'; + +// Immediately executing async function +(async function() { + // Pay 10 XDAI (on Gnosis chain) from the root domain to the following address + // (forced transaction example) + await colony.pay( + '0xb77D57F4959eAfA0339424b83FcFaf9c15407461', + w`10`, + Id.RootDomain, + Tokens.Gnosis.XDAI, + ).force(); +})(); +``` + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `recipient` | `string` | Wallet address of account to send the funds to (also awarded reputation when sending the native token) | +| `amount` | `BigNumberish` | Amount to pay in wei | +| `teamId?` | `BigNumberish` | The team to use to send the funds from. Has to have funding of at least the amount you need to send. See [Colony.moveFundsToTeam](Colony.md#movefundstoteam). Defaults to the Colony's root team | +| `tokenAddress?` | `string` | The address of the token to make the payment in. Default is the Colony's native token | + +#### Returns + +[`TxCreator`](TxCreator.md)<`OneTxPaymentClientV3`, ``"makePaymentFundedFromDomain"``, { `agent?`: `string` ; `fundamentalId?`: `BigNumber` ; `nPayouts?`: `BigNumber` }, [`MetadataType`](../enums/MetadataType.md)\> + +A [TxCreator](TxCreator.md) + +**Event data** + +| Property | Type | Description | +| :------ | :------ | :------ | +| `agent` | string | The address that is responsible for triggering this event | +| `fundamentalId` | BigNumber | The newly added payment id | +| `nPayouts` | BigNumber | Number of payouts in total | + +___ + +### getLatestSupportedVersion + +▸ `Static` **getLatestSupportedVersion**(): ``3`` + +#### Returns + +``3`` diff --git a/docs/api/classes/TxCreator.md b/docs/api/classes/TxCreator.md index 5c758445..4b85b019 100644 --- a/docs/api/classes/TxCreator.md +++ b/docs/api/classes/TxCreator.md @@ -58,7 +58,7 @@ Learn more about these functions in their individual documentation ### force -▸ **force**(): `Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> +▸ **force**(): `Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](../interfaces/ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](../interfaces/DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> Forces an action @@ -68,7 +68,7 @@ The user sending this transaction has to have the appropriate permissions to do #### Returns -`Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> +`Promise`<[`E`, `ContractReceipt`, () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](../interfaces/ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](../interfaces/DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, `ContractReceipt`]\> A tupel of event data and contract receipt (and a function to retrieve metadata if applicable) @@ -76,7 +76,7 @@ ___ ### forceMeta -▸ **forceMeta**(): `Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> +▸ **forceMeta**(): `Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](../interfaces/ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](../interfaces/DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> Forces an action using a gasless metatransaction @@ -86,7 +86,7 @@ The user sending this transaction has to have the appropriate permissions to do #### Returns -`Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> +`Promise`<[`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md), () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](../interfaces/ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](../interfaces/DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`MD`]\>\>] \| [`E`, [`ParsedLogTransactionReceipt`](../interfaces/ParsedLogTransactionReceipt.md)]\> A tupel of event data and contract receipt (and a function to retrieve metadata if applicable) diff --git a/docs/api/interfaces/ColonyEvent.md b/docs/api/interfaces/ColonyEvent.md index b9b8ed6c..106f468d 100644 --- a/docs/api/interfaces/ColonyEvent.md +++ b/docs/api/interfaces/ColonyEvent.md @@ -68,15 +68,15 @@ ___ ### getMetadata -• `Optional` **getMetadata**: () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> +• `Optional` **getMetadata**: () => `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> #### Type declaration -▸ (): `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> +▸ (): `Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> ##### Returns -`Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => `ColonyMetadata` = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => `DomainMetadata` = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> +`Promise`<`ReturnType`<{ `None`: () => `void` ; `annotation`: (`res`: `string`) => `string` = getAnnotationMsgFromResponse; `colony`: (`res`: `string`) => [`ColonyMetadata`](ColonyMetadata.md) = getColonyMetadataFromResponse; `decision`: (`res`: `string`) => `DecisionMetadata` = getDecisionDetailsFromResponse; `domain`: (`res`: `string`) => [`DomainMetadata`](DomainMetadata.md) = getDomainMetadataFromResponse; `misc`: (`res`: `string`) => `MiscMetadata` = getMiscDataFromResponse }[`T`]\>\> ___ diff --git a/docs/api/interfaces/ColonyMetadata.md b/docs/api/interfaces/ColonyMetadata.md new file mode 100644 index 00000000..97a4cc47 --- /dev/null +++ b/docs/api/interfaces/ColonyMetadata.md @@ -0,0 +1,43 @@ +# Interface: ColonyMetadata + +## Properties + +### colonyAvatarHash + +• `Optional` **colonyAvatarHash**: ``null`` \| `string` + +___ + +### colonyDisplayName + +• `Optional` **colonyDisplayName**: `string` + +___ + +### colonyName + +• `Optional` **colonyName**: `string` + +___ + +### colonySafes + +• `Optional` **colonySafes**: `SafeMetadata`[] + +___ + +### colonyTokens + +• `Optional` **colonyTokens**: `string`[] + +___ + +### isWhitelistActivated + +• `Optional` **isWhitelistActivated**: `boolean` + +___ + +### verifiedAddresses + +• `Optional` **verifiedAddresses**: `string`[] diff --git a/docs/api/interfaces/DomainMetadata.md b/docs/api/interfaces/DomainMetadata.md new file mode 100644 index 00000000..5f451908 --- /dev/null +++ b/docs/api/interfaces/DomainMetadata.md @@ -0,0 +1,19 @@ +# Interface: DomainMetadata + +## Properties + +### domainColor + +• `Optional` **domainColor**: `number` + +___ + +### domainName + +• `Optional` **domainName**: `string` + +___ + +### domainPurpose + +• `Optional` **domainPurpose**: `string` diff --git a/docs/api/interfaces/SupportedExtensions.md b/docs/api/interfaces/SupportedExtensions.md index 16128fb9..d853d0f8 100644 --- a/docs/api/interfaces/SupportedExtensions.md +++ b/docs/api/interfaces/SupportedExtensions.md @@ -10,4 +10,4 @@ ___ ### oneTx -• `Optional` **oneTx**: `OneTxPayment` +• `Optional` **oneTx**: [`OneTxPayment`](../classes/OneTxPayment.md) diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index 9c4278bd..4780b1a5 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -12,9 +12,12 @@ import { ColonyMetadataEventObject, TokenDeployedEventObject, } from '@colony/colony-js/extras'; -import { ColonyMetadata } from '@colony/colony-event-metadata-parser'; +import { + ColonyMetadata, + MetadataType, +} from '@colony/colony-event-metadata-parser'; -import { IpfsMetadata, IpfsAdapter, MetadataType } from '../ipfs'; +import { IpfsMetadata, IpfsAdapter } from '../ipfs'; import { Colony, SupportedExtensions } from './Colony'; import { getVotingReputationClient, @@ -135,6 +138,56 @@ export class ColonyNetwork { }); } + /** + * 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]] 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). + * + * @example + * ```typescript + * import { Tokens } from '@colony/sdk'; + * + * // Immediately executing async function + * (async function() { + * // Create a colony with some metadata details attached + * // (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', { + * 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], + * }).force(); + * })(); + * ``` + * + * @param metadata The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [[ColonyMetadata]] 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]] that can upload and pin to IPFS (like the [[PinataAdapter]]). See its documentation for more information. + * + * @returns A [[TxCreator]] + * + * **Event data** + * + * | Property | Type | Description | + * | :------ | :------ | :------ | + * | `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 | + * | `metadata` | string | IPFS CID of metadata attached to this transaction | + * + * **Metadata** (can be obtained by calling and awaiting the `getMetadata` function) + * + * | Property | Type | Description | + * | :------ | :------ | :------ | + * | `colonyDisplayName` | string | The name that should be displayed for the colony | + * | `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: string, label: string, @@ -146,6 +199,37 @@ export class ColonyNetwork { MetadataType.Colony >; + /** + * 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]] 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). + * + * @example + * ```typescript + * // Immediately executing async function + * (async function() { + * // Create a colony + * // (forced transaction example) + * await colonyNetwork + * // Use USDC on Gnosis chain as the native token + * .createColony('0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83') + * .force(); + * })(); + * ``` + * + * @returns A [[TxCreator]] + * + * **Event data** + * + * | Property | Type | Description | + * | :------ | :------ | :------ | + * | `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 | + */ createColony( tokenAddress: string, label: string, @@ -269,6 +353,14 @@ export class ColonyNetwork { return this.getColony(colonyAddress); } + /** + * Get the colony's ENS label + * + * Returns the colony's ENS label, just like it's shown in the browsers address bar after `/colony/`, when using the dApp. + * Will return `null` if the colony does not exist or if no label was assigned yet + * + * @returns The colony's ENS label + */ async getColonyLabel(address: string) { const ensName = await this.networkClient.lookupRegisteredENSDomain(address); if (ensName) { @@ -277,6 +369,14 @@ export class ColonyNetwork { return null; } + /** + * Get the colony's addess by the ENS label + * + * Returns the colony's address that belongs to the given ENS label + * Will return `null` if the given label was not assigned to a colony. + * + * @returns The colony's address + */ async getColonyAddress(label: string) { const hash = namehash(`${label}${ColonyLabelSuffix[this.network]}`); const address = await this.networkClient.addr(hash); @@ -286,6 +386,18 @@ export class ColonyNetwork { return null; } + /** + * 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). + * + * @remarks + * The token deployed with this function is locked by default. Call `unlockToken()` on the Colony at a later point to unlock it. + * + * @returns The colony's address + */ deployToken(name: string, symbol: string, decimals = 18) { return this.createTxCreator( this.networkClient, diff --git a/src/ColonyNetwork/TxCreator.ts b/src/ColonyNetwork/TxCreator.ts index 1cd58a51..f2272ac2 100644 --- a/src/ColonyNetwork/TxCreator.ts +++ b/src/ColonyNetwork/TxCreator.ts @@ -14,10 +14,11 @@ import { utils, } from 'ethers'; import { fetch } from 'cross-fetch'; +import { MetadataType } from '@colony/colony-event-metadata-parser'; import { MotionCreatedEventObject } from '@colony/colony-js/extras'; import { Colony } from './Colony'; -import { MetadataType, MetadataValue } from '../ipfs'; +import { MetadataValue } from '../ipfs'; import { extractEvent } from '../utils'; import { ParsedLogTransactionReceipt } from '../types'; import { IPFS_METADATA_EVENTS } from '../ipfs/IpfsMetadata'; diff --git a/src/ColonyNetwork/index.ts b/src/ColonyNetwork/index.ts index d8dd6836..aede72f2 100644 --- a/src/ColonyNetwork/index.ts +++ b/src/ColonyNetwork/index.ts @@ -6,5 +6,6 @@ export { ColonyNetwork, ColonyNetworkOptions } from './ColonyNetwork'; export { Colony, SupportedExtension, SupportedExtensions } from './Colony'; export { ColonyToken } from './ColonyToken'; +export { OneTxPayment } from './OneTxPayment'; export { VotingReputation, Vote } from './VotingReputation'; export { TxCreator } from './TxCreator'; diff --git a/src/events/ColonyEventManager.ts b/src/events/ColonyEventManager.ts index 197ed7d8..51a5cdf5 100644 --- a/src/events/ColonyEventManager.ts +++ b/src/events/ColonyEventManager.ts @@ -4,6 +4,7 @@ */ import { constants, providers, EventFilter } from 'ethers'; + import type { Result } from 'ethers/lib/utils'; import type { BlockTag } from '@ethersproject/abstract-provider'; import { @@ -16,6 +17,7 @@ import { VotingReputationEvents, VotingReputationEvents__factory, } from '@colony/colony-js/extras'; +import type { MetadataType } from '@colony/colony-event-metadata-parser'; import type { Ethers6Filter } from '../types'; import { addressesAreEqual, getLogs, nonNullable } from '../utils'; @@ -23,7 +25,6 @@ import { IpfsAdapter, IpfsMetadata, MetadataEvent, - MetadataType, MetadataValue, } from '../ipfs'; diff --git a/src/index.ts b/src/index.ts index 96d42949..e82ff415 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,13 @@ export { MotionState, NetworkClientOptions, Tokens } from '@colony/colony-js'; -export type { AnnotationMetadata } from '@colony/colony-event-metadata-parser'; +export type { + AnnotationMetadata, + ColonyMetadata, + DomainMetadata, + MetadataType, +} from '@colony/colony-event-metadata-parser'; export * from './ColonyNetwork'; export * from './events'; -export * from './events'; export * from './ipfs'; export * from './constants'; export * from './utils'; diff --git a/src/ipfs/IpfsMetadata.ts b/src/ipfs/IpfsMetadata.ts index 299b64ad..94f36aaf 100644 --- a/src/ipfs/IpfsMetadata.ts +++ b/src/ipfs/IpfsMetadata.ts @@ -18,8 +18,6 @@ import { import IpfsAdapter from './IpfsAdapter'; import CloudflareReadonlyAdapter from './CloudflareReadonlyAdapter'; -export { MetadataType } from '@colony/colony-event-metadata-parser'; - const fetchRetry = wrapFetch(fetch, { headers: { Accept: 'application/json', diff --git a/src/ipfs/index.ts b/src/ipfs/index.ts index c3866824..82a9f1a8 100644 --- a/src/ipfs/index.ts +++ b/src/ipfs/index.ts @@ -1,9 +1,4 @@ -export { - IpfsMetadata, - MetadataEvent, - MetadataType, - MetadataValue, -} from './IpfsMetadata'; +export { IpfsMetadata, MetadataEvent, MetadataValue } from './IpfsMetadata'; export { default as PinataAdapter } from './PinataAdapter'; export { default as CloudflareReadonlyAdapter } from './CloudflareReadonlyAdapter'; From 355db95ad4e91f6a6f2f3a4fa68103c8ad794039 Mon Sep 17 00:00:00 2001 From: chmanie Date: Mon, 5 Dec 2022 20:44:28 +0900 Subject: [PATCH 08/12] Add colony creation guide template --- docs/guides/colony-creation.md | 7 +++++++ docs/guides/transactions.md | 6 ++++++ 2 files changed, 13 insertions(+) create mode 100644 docs/guides/colony-creation.md diff --git a/docs/guides/colony-creation.md b/docs/guides/colony-creation.md new file mode 100644 index 00000000..5c6ec32a --- /dev/null +++ b/docs/guides/colony-creation.md @@ -0,0 +1,7 @@ +--- +description: A guide on how to create a colony. The deployment of a colony require a few transactions for it to be up and running and fully usable. This guide explains how to go through the whole process in Colony SDK. + +sidebar_position: 0 +--- + +# Creating a colony diff --git a/docs/guides/transactions.md b/docs/guides/transactions.md index 7627eea1..47e4766d 100644 --- a/docs/guides/transactions.md +++ b/docs/guides/transactions.md @@ -1,3 +1,9 @@ +--- +description: A guide on how to create transactions within Colony. You can create motions and even gasless MetaTransactions in a very straightforward and concise way. + +sidebar_position: 0 +--- + # How to create transactions Within Colony, there are a few ways to do an action. As a colony is a permissioned contract, not everyone can just do anything they like, users (or contracts) have to have the right permission in the relevant team to do so. From d285043101422bef7fdf83c2a840237bbce87700 Mon Sep 17 00:00:00 2001 From: chmanie Date: Mon, 5 Dec 2022 20:49:40 +0900 Subject: [PATCH 09/12] Replace role set methods --- docs/api/classes/Colony.md | 32 +++++++++---------- examples/node/create.ts | 18 ++++------- src/ColonyNetwork/Colony.ts | 64 +++++++++++++++++++++++++++++++------ src/utils.ts | 1 + 4 files changed, 78 insertions(+), 37 deletions(-) diff --git a/docs/api/classes/Colony.md b/docs/api/classes/Colony.md index e50f1736..d14a0a7d 100644 --- a/docs/api/classes/Colony.md +++ b/docs/api/classes/Colony.md @@ -482,39 +482,39 @@ A [TxCreator](TxCreator.md) ___ -### setAdministrationRole +### setRoles -▸ **setAdministrationRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +▸ **setRoles**(`address`, `roles`, `teamId?`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters -| Name | Type | -| :------ | :------ | -| `address` | `string` | -| `teamId` | `BigNumberish` | -| `set` | `boolean` | +| Name | Type | Default value | +| :------ | :------ | :------ | +| `address` | `string` | `undefined` | +| `roles` | [`ColonyRole`](../enums/ColonyRole.md) \| [`ColonyRole`](../enums/ColonyRole.md)[] | `undefined` | +| `teamId` | `BigNumberish` | `Id.RootDomain` | #### Returns -[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setAdministrationRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ -### setFundingRole +### unsetRoles -▸ **setFundingRole**(`address`, `teamId`, `set`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +▸ **unsetRoles**(`address`, `roles`, `teamId?`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> #### Parameters -| Name | Type | -| :------ | :------ | -| `address` | `string` | -| `teamId` | `BigNumberish` | -| `set` | `boolean` | +| Name | Type | Default value | +| :------ | :------ | :------ | +| `address` | `string` | `undefined` | +| `roles` | [`ColonyRole`](../enums/ColonyRole.md) \| [`ColonyRole`](../enums/ColonyRole.md)[] | `undefined` | +| `teamId` | `BigNumberish` | `Id.RootDomain` | #### Returns -[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setFundingRole"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +[`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> ___ diff --git a/examples/node/create.ts b/examples/node/create.ts index 3f1fa14b..90033ff2 100644 --- a/examples/node/create.ts +++ b/examples/node/create.ts @@ -1,6 +1,6 @@ import { providers, Wallet } from 'ethers'; -import { ColonyNetwork, ColonyRole, Id, SupportedExtension } from '../../src'; +import { ColonyNetwork, ColonyRole, SupportedExtension } from '../../src'; const provider = new providers.JsonRpcProvider('https://xdai.colony.io/rpc2/'); @@ -54,23 +54,17 @@ const start = async () => { console.error('Could not instantiate OneTx extension within Colony'); return; } - // Give Administration role to OneTxPayment extension + // Give Administration and Funding roles to OneTxPayment extension const [{ user, setTo, role }] = await colony - .setAdministrationRole(colony.ext.oneTx.address, Id.RootDomain, true) + .setRoles(colony.ext.oneTx.address, [ + ColonyRole.Administration, + ColonyRole.Funding, + ]) .force(); if (!role) { return; } console.info(user, setTo, ColonyRole[role]); - // Give Funding role to OneTxPayment extension - const [{ user: fundingUser, setTo: fundingSetTo, role: fundingRole }] = - await colony - .setFundingRole(colony.ext.oneTx.address, Id.RootDomain, true) - .force(); - if (!fundingRole) { - return; - } - console.info(fundingUser, fundingSetTo, ColonyRole[fundingRole]); }; start(); diff --git a/src/ColonyNetwork/Colony.ts b/src/ColonyNetwork/Colony.ts index 15491e96..fdfdfe2c 100644 --- a/src/ColonyNetwork/Colony.ts +++ b/src/ColonyNetwork/Colony.ts @@ -21,13 +21,20 @@ import { DomainMetadataEventObject, ExtensionInstalledEventObject, FundingPotAddedEventObject, + RecoveryRoleSetEventObject, } from '@colony/colony-js/extras'; import { AnnotationMetadata, DomainMetadata, MetadataType, } from '@colony/colony-event-metadata-parser'; -import { BigNumberish, BytesLike, ContractReceipt } from 'ethers'; +import { + BigNumber, + BigNumberish, + BytesLike, + ContractReceipt, + utils, +} from 'ethers'; import type { Expand, Parameters, ParametersFrom2 } from '../types'; @@ -755,12 +762,30 @@ export class Colony { ); } - // TODO: consider using ColonyClient.setRoles in an improved abstraction - setAdministrationRole(address: string, teamId: BigNumberish, set: boolean) { + setRoles( + address: string, + roles: ColonyRole | ColonyRole[], + teamId: BigNumberish = Id.RootDomain, + ) { return this.createPermissionedTxCreator( this.colonyClient, - 'setAdministrationRole', - [address, teamId, set], + 'setUserRoles', + async () => { + const oldRolesHex = await this.colonyClient.getUserRoles( + address, + teamId, + ); + const oldRoles = parseInt(oldRolesHex, 16); + // TODO: export the colonyRoles2Hex helper from ColonyJS + /* eslint-disable no-bitwise */ + const newRoles = + ([] as ColonyRole[]) + .concat(roles) + .reduce((acc, current) => acc | (1 << current), 0) | oldRoles; + /* eslint-enable no-bitwise */ + const hexRoles = utils.hexZeroPad(`0x${newRoles}`, 32); + return [address, teamId, hexRoles] as [string, BigNumber, string]; + }, { roles: ColonyRole.Architecture, domain: teamId, @@ -771,16 +796,36 @@ export class Colony { 'ColonyRoleSet', receipt, ), + ...extractEvent('RecoveryRoleSet', receipt), }), ); } - // TODO: consider using ColonyClient.setRoles in an improved abstraction - setFundingRole(address: string, teamId: BigNumberish, set: boolean) { + unsetRoles( + address: string, + roles: ColonyRole | ColonyRole[], + teamId: BigNumberish = Id.RootDomain, + ) { return this.createPermissionedTxCreator( this.colonyClient, - 'setFundingRole', - [address, teamId, set], + 'setUserRoles', + async () => { + const oldRolesHex = await this.colonyClient.getUserRoles( + address, + teamId, + ); + const oldRoles = parseInt(oldRolesHex, 16); + // TODO: export the colonyRoles2Hex helper from ColonyJS + /* eslint-disable no-bitwise */ + const newRoles = + ([] as ColonyRole[]) + .concat(roles) + .reduce((acc, current) => acc & ~(1 << current), 0b11111) & + oldRoles; + /* eslint-enable no-bitwise */ + const hexRoles = utils.hexZeroPad(`0x${newRoles}`, 32); + return [address, teamId, hexRoles] as [string, BigNumber, string]; + }, { roles: ColonyRole.Architecture, domain: teamId, @@ -791,6 +836,7 @@ export class Colony { 'ColonyRoleSet', receipt, ), + ...extractEvent('RecoveryRoleSet', receipt), }), ); } diff --git a/src/utils.ts b/src/utils.ts index 7bd8891d..e1e502a8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -10,6 +10,7 @@ import { } from './types'; /** Extract event args from a contract receipt */ +// TODO: Make it possible to retrieve multiple events of the same kind export const extractEvent = ( eventName: string, receipt: ContractReceipt | ParsedLogTransactionReceipt, From 0ca2a0b094a6f71eaeb2550ad8b13161d675f93e Mon Sep 17 00:00:00 2001 From: chmanie Date: Tue, 6 Dec 2022 15:07:02 +0900 Subject: [PATCH 10/12] Refactor extension installation, add docs --- docs/api/classes/Colony.md | 145 ++++++++++++++++++++++++--- docs/api/enums/SupportedExtension.md | 6 ++ docs/start.md | 2 +- examples/node/create.ts | 4 +- src/ColonyNetwork/Colony.ts | 143 ++++++++++++++++++++++++-- src/ColonyNetwork/ColonyNetwork.ts | 32 +----- 6 files changed, 278 insertions(+), 54 deletions(-) diff --git a/docs/api/classes/Colony.md b/docs/api/classes/Colony.md index d14a0a7d..28e5307d 100644 --- a/docs/api/classes/Colony.md +++ b/docs/api/classes/Colony.md @@ -70,12 +70,12 @@ If [AnnotationMetadata](../interfaces/AnnotationMetadata.md) is provided directl (async function() { // Create a motion to pay 10 of the native token to some (maybe your own?) address - // (forced transaction example) const [, { transactionHash }] = await colony.ext.oneTx.pay( '0xb77D57F4959eAfA0339424b83FcFaf9c15407461', w`10`, ).motion(); // Annotate the motion transaction with a little explanation :) + // (forced transaction example) await colony.annotateTransaction( transactionHash, { annotationMsg: 'I am creating this motion because I think I deserve a little bonus' }, @@ -365,16 +365,51 @@ ___ ▸ **installExtension**(`extension`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"installExtension"``, { `colony?`: `string` ; `extensionId?`: `string` ; `version?`: `BigNumber` }, [`MetadataType`](../enums/MetadataType.md)\> +Install an extension for a colony + +Valid extensions can be found here: [SupportedExtension](../enums/SupportedExtension.md) + +**`Remarks`** + +* Be aware that some extensions need some extra setup steps (like the `initialise` method on `VotingReputation`). +* After an extension was installed, `colony.updateExtensions()` needs to be called (see example) + +**`Example`** + +```typescript +// Immediately executing async function +(async function() { + // Install the OneTxPayment extension for Colony + // (forced transaction example) + await colony.installExtension( + SupportedExtension.oneTx, + ).force(); + // Update the extensions in the colony + await colony.updateExtensions(); + console.info(colony.ext.oneTx.address); +})(); +``` + #### Parameters -| Name | Type | -| :------ | :------ | -| `extension` | [`SupportedExtension`](../enums/SupportedExtension.md) | +| Name | Type | Description | +| :------ | :------ | :------ | +| `extension` | [`SupportedExtension`](../enums/SupportedExtension.md) | Name of the extension you'd like to install | #### Returns [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"installExtension"``, { `colony?`: `string` ; `extensionId?`: `string` ; `version?`: `BigNumber` }, [`MetadataType`](../enums/MetadataType.md)\> +A [TxCreator](TxCreator.md) + +**Event data** + +| Property | Type | Description | +| :------ | :------ | :------ | +| `extensionId` | string | Id (name) of the extension (e.g. `OneTxPayment`) | +| `colony` | string | The address of the colony on which the extension was installed | +| `version` | BigNumber | The version of the extension that was installed | + ___ ### makeArbitraryTransaction @@ -486,36 +521,101 @@ ___ ▸ **setRoles**(`address`, `roles`, `teamId?`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +Set (award) roles to a user/contract + +**`Remarks`** + +Existing roles will be kept. Use [unsetRoles](Colony.md#unsetroles) to remove roles + +**`Example`** + +```typescript +import { ColonyRole } from '@colony/sdk'; + +// Immediately executing async function +(async function() { + // Give Administration and Root role to address 0xb794f5ea0ba39494ce839613fffba74279579268 (in Root team) + // (forced transaction example) + await colony.setRoles( + '0xb794f5ea0ba39494ce839613fffba74279579268', + [ColonyRole.Administration, ColonyRole.Root], + ).force(); +})(); +``` + #### Parameters -| Name | Type | Default value | -| :------ | :------ | :------ | -| `address` | `string` | `undefined` | -| `roles` | [`ColonyRole`](../enums/ColonyRole.md) \| [`ColonyRole`](../enums/ColonyRole.md)[] | `undefined` | -| `teamId` | `BigNumberish` | `Id.RootDomain` | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `address` | `string` | `undefined` | Address of the wallet or contract to give the roles to | +| `roles` | [`ColonyRole`](../enums/ColonyRole.md) \| [`ColonyRole`](../enums/ColonyRole.md)[] | `undefined` | Role or array of roles to award | +| `teamId` | `BigNumberish` | `Id.RootDomain` | Team to apply the role(s) in | #### Returns [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +A [TxCreator](TxCreator.md) + +**Event data** +*Heads up!* This event is emitted for every role that was set + +| Property | Type | Description | +| :------ | :------ | :------ | +| `agent` | string | The address that is responsible for triggering this event | +| `user` | string | Address of the user who was awarded the role | +| `domainId` | BigNumber | The team the role was awarded for | +| `role` | number | The number of the role that was awarded. Use `ColonyRole[role]` to get the title of the role | +| `setTo` | number | Whether the role was awarded or removed | + ___ ### unsetRoles ▸ **unsetRoles**(`address`, `roles`, `teamId?`): [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +Unset (remove) roles from a user/contract + #### Parameters -| Name | Type | Default value | -| :------ | :------ | :------ | -| `address` | `string` | `undefined` | -| `roles` | [`ColonyRole`](../enums/ColonyRole.md) \| [`ColonyRole`](../enums/ColonyRole.md)[] | `undefined` | -| `teamId` | `BigNumberish` | `Id.RootDomain` | +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `address` | `string` | `undefined` | Address of the wallet or contract to remove the roles from | +| `roles` | [`ColonyRole`](../enums/ColonyRole.md) \| [`ColonyRole`](../enums/ColonyRole.md)[] | `undefined` | Role or array of roles to remove | +| `teamId` | `BigNumberish` | `Id.RootDomain` | Team to apply the role(s) in | #### Returns [`TxCreator`](TxCreator.md)<`ColonyClientV10`, ``"setUserRoles"``, { `agent?`: `string` ; `domainId?`: `BigNumber` ; `role?`: `number` ; `setTo?`: `boolean` ; `user?`: `string` }, [`MetadataType`](../enums/MetadataType.md)\> +A [TxCreator](TxCreator.md) + +**Event data** +*Heads up!* This event is emitted for every role that was unset + +| Property | Type | Description | +| :------ | :------ | :------ | +| `agent` | string | The address that is responsible for triggering this event | +| `user` | string | Address of the user of which the role was removed | +| `domainId` | BigNumber | The team the role was removed for | +| `role` | number | The number of the role that was removed. Use `ColonyRole[role]` to get the title of the role | +| `setTo` | number | Whether the role was awarded or removed | + +___ + +### updateExtensions + +▸ **updateExtensions**(): `Promise`<`void`\> + +Refresh colony extensions + +Call this function after a new extension was installed. +It will then become available under `colony.ext` + +#### Returns + +`Promise`<`void`\> + ___ ### getLatestSupportedVersion @@ -525,3 +625,20 @@ ___ #### Returns ``10`` + +___ + +### init + +▸ `Static` **init**(`colonyNetwork`, `colonyClient`): `Promise`<[`Colony`](Colony.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `colonyNetwork` | [`ColonyNetwork`](ColonyNetwork.md) | +| `colonyClient` | `ColonyClientV10` | + +#### Returns + +`Promise`<[`Colony`](Colony.md)\> diff --git a/docs/api/enums/SupportedExtension.md b/docs/api/enums/SupportedExtension.md index ca24938e..865a549a 100644 --- a/docs/api/enums/SupportedExtension.md +++ b/docs/api/enums/SupportedExtension.md @@ -1,13 +1,19 @@ # Enumeration: SupportedExtension +Extensions that are supported by Colony SDK + ## Enumeration Members ### motion • **motion** = ``"motion"`` +Motions & Disputes (VotingReputation) + ___ ### oneTx • **oneTx** = ``"oneTx"`` + +One Transaction Payment (OneTxPayment - enabled by default in Dapp created colonies) diff --git a/docs/start.md b/docs/start.md index 7b64986c..c70fe131 100644 --- a/docs/start.md +++ b/docs/start.md @@ -42,7 +42,7 @@ import { providers } from 'ethers'; import { ColonyNetwork, toEth } from '@colony/sdk'; // If MetaMask is installed there will be an `ethereum` object on the `window` -// NOTE: Make sure MetaMask is connected to Gnosis chain (see https://www.xdaichain.com/for-users/wallets/metamask/metamask-setup) +// NOTE: Make sure MetaMask is connected to Gnosis chain (see https://docs.gnosischain.com/tools/wallets/metamask) const provider = new providers.Web3Provider(window.ethereum); // Get the Colony's XDAI funding in the ROOT pot (id 1) diff --git a/examples/node/create.ts b/examples/node/create.ts index 90033ff2..ddc06130 100644 --- a/examples/node/create.ts +++ b/examples/node/create.ts @@ -27,7 +27,7 @@ const start = async () => { } console.info('Colony address', colonyAddress); // Instantiate colony and token - let colony = await colonyNetwork.getColony(colonyAddress); + const colony = await colonyNetwork.getColony(colonyAddress); const token = await colony.getToken(); // Deploy TokanAuthority const [{ tokenAuthorityAddress }] = await token @@ -49,7 +49,7 @@ const start = async () => { console.info('ExtensionId', extensionId); console.info('Extension version', version); // Intantiate Colony again to update the extensions - colony = await colonyNetwork.getColony(colonyAddress); + await colony.updateExtensions(); if (!colony.ext.oneTx) { console.error('Could not instantiate OneTx extension within Colony'); return; diff --git a/src/ColonyNetwork/Colony.ts b/src/ColonyNetwork/Colony.ts index fdfdfe2c..87d72095 100644 --- a/src/ColonyNetwork/Colony.ts +++ b/src/ColonyNetwork/Colony.ts @@ -41,15 +41,21 @@ import type { Expand, Parameters, ParametersFrom2 } from '../types'; import { extractEvent, extractCustomEvent } from '../utils'; import { ColonyToken } from './ColonyToken'; import { ColonyNetwork } from './ColonyNetwork'; -import { OneTxPayment } from './OneTxPayment'; -import { VotingReputation } from './VotingReputation'; +import { getOneTxPaymentClient, OneTxPayment } from './OneTxPayment'; +import { + getVotingReputationClient, + VotingReputation, +} from './VotingReputation'; import { PermissionConfig, TxCreator } from './TxCreator'; export type SupportedColonyClient = ColonyClientV10; export type SupportedColonyMethods = SupportedColonyClient['functions']; +/** Extensions that are supported by Colony SDK */ export enum SupportedExtension { + /** Motions & Disputes (VotingReputation) */ motion = 'motion', + /** One Transaction Payment (OneTxPayment - enabled by default in Dapp created colonies) */ oneTx = 'oneTx', } @@ -111,6 +117,15 @@ export class Colony { this.version = colonyClient.clientVersion; } + static async init( + colonyNetwork: ColonyNetwork, + colonyClient: SupportedColonyClient, + ) { + const colony = new Colony(colonyNetwork, colonyClient); + await colony.updateExtensions(); + return colony; + } + static getLatestSupportedVersion() { return Colony.supportedVersions[Colony.supportedVersions.length - 1]; } @@ -225,11 +240,34 @@ export class Colony { } /** - * Installs colony extensions that can be instantiated in the callback function - * @internal + * Refresh colony extensions + * + * Call this function after a new extension was installed. + * It will then become available under `colony.ext` */ - installExtensions(extensions: SupportedExtensions) { - this.ext = extensions; + async updateExtensions() { + // NOTE: Create an individual try-catch block for every extension + if (!this.ext.motions) { + try { + const votingReputationClient = await getVotingReputationClient( + this.colonyClient, + ); + this.ext.motions = new VotingReputation(this, votingReputationClient); + } catch (e) { + // Ignore error here. Extension just won't be available. + } + } + + if (!this.ext.oneTx) { + try { + const oneTxPaymentClient = await getOneTxPaymentClient( + this.colonyClient, + ); + this.ext.oneTx = new OneTxPayment(this, oneTxPaymentClient); + } catch (e) { + // Ignore error here. Extension just won't be available. + } + } } /** @@ -687,12 +725,12 @@ export class Colony { * (async function() { * * // Create a motion to pay 10 of the native token to some (maybe your own?) address - * // (forced transaction example) * const [, { transactionHash }] = await colony.ext.oneTx.pay( * '0xb77D57F4959eAfA0339424b83FcFaf9c15407461', * w`10`, * ).motion(); * // Annotate the motion transaction with a little explanation :) + * // (forced transaction example) * await colony.annotateTransaction( * transactionHash, * { annotationMsg: 'I am creating this motion because I think I deserve a little bonus' }, @@ -738,6 +776,41 @@ export class Colony { ); } + /** + * Install an extension for a colony + * + * Valid extensions can be found here: [[SupportedExtension]] + * + * @remarks + * * Be aware that some extensions need some extra setup steps (like the `initialise` method on `VotingReputation`). + * * After an extension was installed, `colony.updateExtensions()` needs to be called (see example) + * + * @example + * ```typescript + * // Immediately executing async function + * (async function() { + * // Install the OneTxPayment extension for Colony + * // (forced transaction example) + * await colony.installExtension( + * SupportedExtension.oneTx, + * ).force(); + * // Update the extensions in the colony + * await colony.updateExtensions(); + * console.info(colony.ext.oneTx.address); + * })(); + * ``` + * + * @param extension Name of the extension you'd like to install + * @returns A [[TxCreator]] + * + * **Event data** + * + * | Property | Type | Description | + * | :------ | :------ | :------ | + * | `extensionId` | string | Id (name) of the extension (e.g. `OneTxPayment`) | + * | `colony` | string | The address of the colony on which the extension was installed | + * | `version` | BigNumber | The version of the extension that was installed | + */ installExtension(extension: SupportedExtension) { const Extension = supportedExtensionMap[extension]; const version = Extension.getLatestSupportedVersion(); @@ -762,6 +835,43 @@ export class Colony { ); } + /** + * Set (award) roles to a user/contract + * + * @remarks + * Existing roles will be kept. Use [[unsetRoles]] to remove roles + * + * @example + * ```typescript + * import { ColonyRole } from '@colony/sdk'; + * + * // Immediately executing async function + * (async function() { + * // Give Administration and Root role to address 0xb794f5ea0ba39494ce839613fffba74279579268 (in Root team) + * // (forced transaction example) + * await colony.setRoles( + * '0xb794f5ea0ba39494ce839613fffba74279579268', + * [ColonyRole.Administration, ColonyRole.Root], + * ).force(); + * })(); + * ``` + * + * @param address Address of the wallet or contract to give the roles to + * @param roles Role or array of roles to award + * @param teamId Team to apply the role(s) in + * @returns A [[TxCreator]] + * + * **Event data** + * *Heads up!* This event is emitted for every role that was set + * + * | Property | Type | Description | + * | :------ | :------ | :------ | + * | `agent` | string | The address that is responsible for triggering this event | + * | `user` | string | Address of the user who was awarded the role | + * | `domainId` | BigNumber | The team the role was awarded for | + * | `role` | number | The number of the role that was awarded. Use `ColonyRole[role]` to get the title of the role | + * | `setTo` | number | Whether the role was awarded or removed | + */ setRoles( address: string, roles: ColonyRole | ColonyRole[], @@ -801,6 +911,25 @@ export class Colony { ); } + /** + * Unset (remove) roles from a user/contract + * + * @param address Address of the wallet or contract to remove the roles from + * @param roles Role or array of roles to remove + * @param teamId Team to apply the role(s) in + * @returns A [[TxCreator]] + * + * **Event data** + * *Heads up!* This event is emitted for every role that was unset + * + * | Property | Type | Description | + * | :------ | :------ | :------ | + * | `agent` | string | The address that is responsible for triggering this event | + * | `user` | string | Address of the user of which the role was removed | + * | `domainId` | BigNumber | The team the role was removed for | + * | `role` | number | The number of the role that was removed. Use `ColonyRole[role]` to get the title of the role | + * | `setTo` | number | Whether the role was awarded or removed | + */ unsetRoles( address: string, roles: ColonyRole | ColonyRole[], diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index 4780b1a5..07e48408 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -18,12 +18,7 @@ import { } from '@colony/colony-event-metadata-parser'; import { IpfsMetadata, IpfsAdapter } from '../ipfs'; -import { Colony, SupportedExtensions } from './Colony'; -import { - getVotingReputationClient, - VotingReputation, -} from './VotingReputation'; -import { getOneTxPaymentClient, OneTxPayment } from './OneTxPayment'; +import { Colony } from './Colony'; import { ColonyLabelSuffix, MetaTxBroadCasterEndpoint } from '../constants'; import { Expand, Parameters } from '../types'; import { TxCreator } from './TxCreator'; @@ -315,30 +310,7 @@ export class ColonyNetwork { ); } - const colony = new Colony(this, colonyClient); - - const extensions: SupportedExtensions = {}; - - // NOTE: Create an individual try-catch block for every extension - try { - const votingReputationClient = await getVotingReputationClient( - colonyClient, - ); - extensions.motions = new VotingReputation(colony, votingReputationClient); - } catch (e) { - // Ignore error here. Extension just won't be available. - } - - try { - const oneTxPaymentClient = await getOneTxPaymentClient(colonyClient); - extensions.oneTx = new OneTxPayment(colony, oneTxPaymentClient); - } catch (e) { - // Ignore error here. Extension just won't be available. - } - - colony.installExtensions(extensions); - - return colony; + return Colony.init(this, colonyClient); } /** From b963acb01b6c1c024b4e8be9ecbb65cefac1a7e7 Mon Sep 17 00:00:00 2001 From: chmanie Date: Tue, 6 Dec 2022 15:30:35 +0900 Subject: [PATCH 11/12] Add eslint doc checker and fix all docs --- .eslintrc | 12 +-- docs/api/classes/Colony.md | 8 +- docs/api/classes/ColonyEventManager.md | 8 +- examples/browser/src/index.ts | 2 + examples/browser/src/metamask.ts | 1 + examples/browser/src/motions.ts | 2 + package-lock.json | 94 +++++++++++++++++++ package.json | 1 + src/ColonyNetwork/Colony.ts | 119 ++++++++++--------------- src/ColonyNetwork/ColonyNetwork.ts | 18 ++-- src/ColonyNetwork/ColonyToken.ts | 16 ++-- src/ColonyNetwork/OneTxPayment.ts | 8 +- src/ColonyNetwork/VotingReputation.ts | 32 +++---- src/ColonyNetwork/index.ts | 5 -- src/events/ColonyEventManager.ts | 41 ++++----- src/events/index.ts | 5 -- src/graph/index.ts | 2 +- src/ipfs/IpfsAdapter.ts | 4 +- 18 files changed, 221 insertions(+), 157 deletions(-) diff --git a/.eslintrc b/.eslintrc index e2d47982..3c81d22f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,8 @@ "@colony/eslint-config-colony" ], "plugins": [ - "@typescript-eslint" + "@typescript-eslint", + "eslint-plugin-tsdoc" ], "env": { "browser": true, @@ -22,12 +23,12 @@ ] } ], - "no-unused-vars": "off", + "no-dupe-class-members": "off", "no-redeclare": "off", + "no-shadow": "off", + "no-unused-vars": "off", "no-use-before-define": "off", - "no-dupe-class-members": "off", "@typescript-eslint/no-unused-vars": "error", - "no-shadow": "off", "@typescript-eslint/no-shadow": [ "error" ], @@ -44,7 +45,8 @@ "examples/browser/src/*.ts" ] } - ] + ], + "tsdoc/syntax": "warn" }, "overrides": [ { diff --git a/docs/api/classes/Colony.md b/docs/api/classes/Colony.md index 28e5307d..a6c40ed8 100644 --- a/docs/api/classes/Colony.md +++ b/docs/api/classes/Colony.md @@ -371,8 +371,8 @@ Valid extensions can be found here: [SupportedExtension](../enums/SupportedExten **`Remarks`** -* Be aware that some extensions need some extra setup steps (like the `initialise` method on `VotingReputation`). -* After an extension was installed, `colony.updateExtensions()` needs to be called (see example) +Be aware that some extensions need some extra setup steps (like the `initialise` method on `VotingReputation`). +After an extension was installed, `colony.updateExtensions()` needs to be called (see example) **`Example`** @@ -558,7 +558,7 @@ import { ColonyRole } from '@colony/sdk'; A [TxCreator](TxCreator.md) **Event data** -*Heads up!* This event is emitted for every role that was set +Heads up!* This event is emitted for every role that was set | Property | Type | Description | | :------ | :------ | :------ | @@ -591,7 +591,7 @@ Unset (remove) roles from a user/contract A [TxCreator](TxCreator.md) **Event data** -*Heads up!* This event is emitted for every role that was unset +Heads up!* This event is emitted for every role that was unset | Property | Type | Description | | :------ | :------ | :------ | diff --git a/docs/api/classes/ColonyEventManager.md b/docs/api/classes/ColonyEventManager.md index 1783f8e7..c98745a8 100644 --- a/docs/api/classes/ColonyEventManager.md +++ b/docs/api/classes/ColonyEventManager.md @@ -89,7 +89,7 @@ Filter for all `DomainAdded` events between block 21830000 and 21840000 (across | `eventName` | `N` | A valid event signature from the contract's `filters` object | | `address?` | `string` | Address of the contract that can emit this event | | `params?` | `Parameters`<`T`[``"filters"``][`N`]\> | Parameters to filter by for the event. Has to be indexed in the contract (see _ethers_ [Event Filters](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters)) | -| `options?` | `Object` | You can define `fromBlock` and `toBlock` only once for all the filters given | +| `options?` | `Object` | You can define `fromBlock` and `toBlock` only once for all the filters given (default for both is `latest`) | | `options.fromBlock?` | `BlockTag` | - | | `options.toBlock?` | `BlockTag` | - | @@ -238,9 +238,9 @@ const domainMetadata = colonyEvents.createMultiFilter( | Name | Type | Description | | :------ | :------ | :------ | | `filters` | [`ColonyMultiFilter`](../interfaces/ColonyMultiFilter.md)[] | An array of [ColonyMultiFilter](../interfaces/ColonyMultiFilter.md)s. Normal [ColonyFilter](../interfaces/ColonyFilter.md)s will not work | -| `options` | `Object` | You can define `fromBlock` and `toBlock` only once for all the filters given | -| `options.fromBlock?` | `BlockTag` | Starting block in which to look for this event - inclusive (default: 'latest') | -| `options.toBlock?` | `BlockTag` | Ending block in which to look for this event - inclusive (default: 'latest') | +| `options` | `Object` | You can define `fromBlock` and `toBlock` only once for all the filters given (default for both is `latest`) | +| `options.fromBlock?` | `BlockTag` | - | +| `options.toBlock?` | `BlockTag` | - | #### Returns diff --git a/examples/browser/src/index.ts b/examples/browser/src/index.ts index 8d1b6df4..60320ac2 100644 --- a/examples/browser/src/index.ts +++ b/examples/browser/src/index.ts @@ -1,4 +1,6 @@ const addColonyRPC = () => { + // If MetaMask is installed there will be an `ethereum` object on the `window` + // eslint-disable-next-line @typescript-eslint/no-explicit-any (window as any).ethereum.request({ method: 'wallet_addEthereumChain', params: [ diff --git a/examples/browser/src/metamask.ts b/examples/browser/src/metamask.ts index 41440191..5b339789 100644 --- a/examples/browser/src/metamask.ts +++ b/examples/browser/src/metamask.ts @@ -2,6 +2,7 @@ import { providers, Signer } from 'ethers'; import { ColonyNetwork } from '../../../src'; // If MetaMask is installed there will be an `ethereum` object on the `window` +// eslint-disable-next-line @typescript-eslint/no-explicit-any const provider = new providers.Web3Provider((window as any).ethereum); // Get the Colony's XDAI funding in the ROOT pot (id 1) diff --git a/examples/browser/src/motions.ts b/examples/browser/src/motions.ts index 34f88b36..d8fccdeb 100644 --- a/examples/browser/src/motions.ts +++ b/examples/browser/src/motions.ts @@ -10,6 +10,8 @@ import { } from '../../../src'; const { isAddress } = utils; +// If MetaMask is installed there will be an `ethereum` object on the `window` +// eslint-disable-next-line @typescript-eslint/no-explicit-any const provider = new providers.Web3Provider((window as any).ethereum); let currentWalletAddress: string; diff --git a/package-lock.json b/package-lock.json index ee7d52c3..55d5ed7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-tsdoc": "^0.2.17", "ethers": "^5.7.1", "fast-glob": "^3.2.11", "husky": "^7.0.4", @@ -1255,6 +1256,37 @@ "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" }, + "node_modules/@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3676,6 +3708,16 @@ } } }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -5132,6 +5174,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -8895,6 +8943,36 @@ "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" }, + "@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + }, + "dependencies": { + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -10581,6 +10659,16 @@ "prettier-linter-helpers": "^1.0.0" } }, + "eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -11600,6 +11688,12 @@ "iterate-iterator": "^1.0.1" } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", diff --git a/package.json b/package.json index cf8ec3d6..79f45025 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-tsdoc": "^0.2.17", "ethers": "^5.7.1", "fast-glob": "^3.2.11", "husky": "^7.0.4", diff --git a/src/ColonyNetwork/Colony.ts b/src/ColonyNetwork/Colony.ts index 87d72095..cc73c616 100644 --- a/src/ColonyNetwork/Colony.ts +++ b/src/ColonyNetwork/Colony.ts @@ -70,7 +70,8 @@ export interface SupportedExtensions { } export class Colony { - /** The currently supported Colony version. If a Colony is not on this version it has to be upgraded. + /** + * The currently supported Colony version. If a Colony is not on this version it has to be upgraded. * If this is not an option, Colony SDK might throw errors at certain points. Usage of ColonyJS is advised in these cases */ static supportedVersions: 10[] = [10]; @@ -96,13 +97,13 @@ export class Colony { /** * Creates a new instance to connect to an existing Colony + * * @internal * * @remarks * Do not use this method directly but use [[ColonyNetwork.getColony]] - * - * @param colonyNetwork A Colony SDK `ColonyNetwork` instance - * @param colonyClient A ColonyJS `ColonyClient` in the latest supported version + * @param colonyNetwork - A Colony SDK `ColonyNetwork` instance + * @param colonyClient - A ColonyJS `ColonyClient` in the latest supported version * @returns A [[Colony]] abstaction instance */ constructor( @@ -132,16 +133,15 @@ export class Colony { /** * Creates a new [[TxCreator]] for non-permissioned Colony transactions - * @internal * + * @internal * @remarks * Do not use this method directly but rather the class methods in the Colony or extensions - * - * @param contract A ColonyJS contract - * @param method The transaction method to execute on the contract - * @param args The arguments for the method - * @param eventData A function that extracts the relevant event data from the [[ContractReceipt]] - * @param metadataType The [[MetadataType]] if the event contains metadata + * @param contract - A ColonyJS contract + * @param method - The transaction method to execute on the contract + * @param args - The arguments for the method + * @param eventData - A function that extracts the relevant event data from the [[ContractReceipt]] + * @param metadataType - The [[MetadataType]] if the event contains metadata * @returns A [[TxCreator]] */ createTxCreator< @@ -171,17 +171,16 @@ export class Colony { /** * Creates a new [[TxCreator]] for permissioned Colony transactions - * @internal * + * @internal * @remarks * Do not use this method directly but rather the class methods in the Colony or extensions - * - * @param contract A ColonyJS contract - * @param method The transaction method to execute on the contract - * @param args The arguments for the method - * @param permissionConfig Relevant configuration for the permissioned Colony function - * @param eventData A function that extracts the relevant event data from the [[ContractReceipt]] - * @param metadataType The [[MetadataType]] if the event contains metadata + * @param contract - A ColonyJS contract + * @param method - The transaction method to execute on the contract + * @param args - The arguments for the method + * @param permissionConfig - Relevant configuration for the permissioned Colony function + * @param eventData - A function that extracts the relevant event data from the [[ContractReceipt]] + * @param metadataType - The [[MetadataType]] if the event contains metadata * @returns A permissioned [[TxCreator]] */ createPermissionedTxCreator< @@ -213,8 +212,8 @@ export class Colony { /** * Provide direct access to the internally used ColonyJS client. Only use when you know what you're doing - * @internal * + * @internal * @returns The internally used ColonyClient */ getInternalColonyClient(): SupportedColonyClient { @@ -223,8 +222,8 @@ export class Colony { /** * Gets the colony's [[ColonyToken]]. Will instantiate it if it doesn't exist yet - * @internal * + * @internal * @returns The colony's [[ColonyToken]] */ async getToken(): Promise { @@ -275,7 +274,6 @@ export class Colony { * * @remarks * The function will automatically figure out the corresponding pot for the given domain, as this is what's usually expected. - * * @example * Get the xDAI balance of the team number 2 * ```typescript @@ -286,9 +284,8 @@ export class Colony { * // This will format the balance as a string in eth and not wei (i.e. 1.0 vs. 1000000000000000000) * console.info(toEth(balance)); * ``` - * - * @param tokenAddress The address of the token to get the balance for. Default is the Colony's native token - * @param teamId The teamId (domainId) of the team to get the balance for. Default is the `Root` team + * @param tokenAddress - The address of the token to get the balance for. Default is the Colony's native token + * @param teamId - The teamId (domainId) of the team to get the balance for. Default is the `Root` team * @returns A token balance in [wei](https://gwei.io/) */ async getBalance(tokenAddress?: string, teamId?: BigNumberish) { @@ -306,7 +303,6 @@ export class Colony { * * @remarks * Currently you can only add domains within the `Root` domain. This restriction will be lifted soon - * * @example * ```typescript * import { TeamColor } from '@colony/sdk'; @@ -323,9 +319,7 @@ export class Colony { * }).force(); * })(); * ``` - * - * @param metadata The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [[DomainMetadata]] 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]] that can upload and pin to IPFS (like the [[PinataAdapter]]). See its documentation for more information. - * + * @param metadata - The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [[DomainMetadata]] 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]] that can upload and pin to IPFS (like the [[PinataAdapter]]). See its documentation for more information. * @returns A [[TxCreator]] * * **Event data** @@ -362,7 +356,6 @@ export class Colony { * * @remarks * Currently you can only add domains within the `Root` domain. This restriction will be lifted soon - * * @returns A [[TxCreator]] * * **Event data** @@ -442,9 +435,8 @@ export class Colony { * * Teams can be deprecated which will remove them from the UI. As they can't be deleted you can always undeprecate a team by passing `false` as the second argument. * - * @param teamId Team to be (un)deprecated - * @param deprecated `true`: Deprecate team; `false`: Undeprecate team - * + * @param teamId - Team to be (un)deprecated + * @param deprecated - `true`: Deprecate team; `false`: Undeprecate team * @returns A [[TxCreator]] * * **Event data** @@ -477,9 +469,7 @@ export class Colony { * Gets the team for `teamId` * * @remarks Will throw if teamId does not exist - * - * @param teamId The teamId to get the team information for - * + * @param teamId - The teamId to get the team information for * @returns A Team object */ async getTeam( @@ -498,9 +488,7 @@ export class Colony { * Anyone can call this function. Claims funds _for_ the Colony that have been sent to the Colony's contract address or minted funds of the Colony's native token. This function _has_ to be called in order for the funds to appear in the Colony's treasury. You can provide a token address for the token to be claimed. Otherwise it will claim the outstanding funds of the Colony's native token * * @remarks use `ethers.constants.AddressZero` to claim ETH. - * - * @param tokenAddress The address of the token to claim the funds for. Default is the Colony's native token - * + * @param tokenAddress - The address of the token to claim the funds for. Default is the Colony's native token * @returns A [[TxCreator]] * * **Event data** @@ -534,7 +522,6 @@ export class Colony { * After sending funds to and claiming funds for your Colony they will land in a special team, the root team. If you want to make payments from other teams (in order to award reputation in that team) you have to move the funds there first. Use this method to do so. * * @remarks Requires the `Funding` permission in the root team. As soon as teams can be nested, this requires the `Funding` permission in a team that is a parent of both teams in which funds are moved. - * * @example * ```typescript * import { Tokens, w } from '@colony/sdk'; @@ -550,11 +537,10 @@ export class Colony { * ).force(); * })(); * ``` - * - * @param amount Amount to transfer between the teams - * @param toTeam The team to transfer the funds to - * @param fromTeam The team to transfer the funds from. Default is the Root team - * @param tokenAddress The address of the token to be transferred. Default is the Colony's native token + * @param amount - Amount to transfer between the teams + * @param toTeam - The team to transfer the funds to + * @param fromTeam - The team to transfer the funds from. Default is the Root team + * @param tokenAddress - The address of the token to be transferred. Default is the Colony's native token * @returns A [[TxCreator]] * * **Event data** @@ -644,8 +630,8 @@ export class Colony { /** * Get the reputation for a user address within a team in the Colony * - * @param userAddress The address of the account to check the reputation for - * @param teamId The teamId (domainId) of the team to get the reputation for. Default is the `Root` team + * @param userAddress - The address of the account to check the reputation for + * @param teamId - The teamId (domainId) of the team to get the reputation for. Default is the `Root` team * @returns A number quantifying the user addresses' reputation */ async getReputation(userAddress: string, teamId = Id.RootDomain) { @@ -658,7 +644,7 @@ export class Colony { /** * Get the reputation for a user address across all teams in the Colony * - * @param userAddress The address of the account to check the reputation for + * @param userAddress - The address of the account to check the reputation for * @returns An array of objects containing the following * * | Property | Description | @@ -697,9 +683,8 @@ export class Colony { * ).force(); * })(); * ``` - * - * @param target Address of the contract to execute a method on - * @param action Encoded action to execute + * @param target - Address of the contract to execute a method on + * @param action - Encoded action to execute * @returns A [[TxCreator]] * * **No event data** @@ -718,7 +703,6 @@ export class Colony { * This will annotate a transaction with an arbitrary text message. This only really works for transactions that happened within this Colony. This will upload the text string to IPFS and connect the transaction to the IPFS hash accordingly. * * @remarks If [[AnnotationMetadata]] 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]] that can upload and pin to IPFS. See its documentation for more information. Keep in mind that **the annotation itself is a transaction**. - * * @example * ```typescript * // Immediately executing async function @@ -737,9 +721,8 @@ export class Colony { * ).force(); * })(); * ``` - * - * @param txHash Transaction hash of the transaction to annotate (within the Colony) - * @param annotationMetadata The annotation metadata you would like to annotate the transaction with (or an IPFS CID pointing to valid metadata) + * @param txHash - Transaction hash of the transaction to annotate (within the Colony) + * @param annotationMetadata - The annotation metadata you would like to annotate the transaction with (or an IPFS CID pointing to valid metadata) * @returns A [[TxCreator]] * * **Event data** @@ -782,9 +765,8 @@ export class Colony { * Valid extensions can be found here: [[SupportedExtension]] * * @remarks - * * Be aware that some extensions need some extra setup steps (like the `initialise` method on `VotingReputation`). - * * After an extension was installed, `colony.updateExtensions()` needs to be called (see example) - * + * Be aware that some extensions need some extra setup steps (like the `initialise` method on `VotingReputation`). + * After an extension was installed, `colony.updateExtensions()` needs to be called (see example) * @example * ```typescript * // Immediately executing async function @@ -799,8 +781,7 @@ export class Colony { * console.info(colony.ext.oneTx.address); * })(); * ``` - * - * @param extension Name of the extension you'd like to install + * @param extension - Name of the extension you'd like to install * @returns A [[TxCreator]] * * **Event data** @@ -840,7 +821,6 @@ export class Colony { * * @remarks * Existing roles will be kept. Use [[unsetRoles]] to remove roles - * * @example * ```typescript * import { ColonyRole } from '@colony/sdk'; @@ -855,14 +835,13 @@ export class Colony { * ).force(); * })(); * ``` - * - * @param address Address of the wallet or contract to give the roles to - * @param roles Role or array of roles to award - * @param teamId Team to apply the role(s) in + * @param address - Address of the wallet or contract to give the roles to + * @param roles - Role or array of roles to award + * @param teamId - Team to apply the role(s) in * @returns A [[TxCreator]] * * **Event data** - * *Heads up!* This event is emitted for every role that was set + * Heads up!* This event is emitted for every role that was set * * | Property | Type | Description | * | :------ | :------ | :------ | @@ -914,13 +893,13 @@ export class Colony { /** * Unset (remove) roles from a user/contract * - * @param address Address of the wallet or contract to remove the roles from - * @param roles Role or array of roles to remove - * @param teamId Team to apply the role(s) in + * @param address - Address of the wallet or contract to remove the roles from + * @param roles - Role or array of roles to remove + * @param teamId - Team to apply the role(s) in * @returns A [[TxCreator]] * * **Event data** - * *Heads up!* This event is emitted for every role that was unset + * Heads up!* This event is emitted for every role that was unset * * | Property | Type | Description | * | :------ | :------ | :------ | diff --git a/src/ColonyNetwork/ColonyNetwork.ts b/src/ColonyNetwork/ColonyNetwork.ts index 07e48408..f150dacd 100644 --- a/src/ColonyNetwork/ColonyNetwork.ts +++ b/src/ColonyNetwork/ColonyNetwork.ts @@ -70,8 +70,8 @@ export class ColonyNetwork { * // Now you could call functions on the colonyNetwork, like `colonyNetwork.getMetaColony()` * ``` * - * @param signerOrProvider An _ethers_ compatible Signer or Provider instance - * @param options Optional custom [[ColonyNetworkOptions]] + * @param signerOrProvider - An _ethers_ compatible Signer or Provider instance + * @param options - Optional custom [[ColonyNetworkOptions]] * @returns A ColonyNetwork abstraction instance */ constructor( @@ -102,11 +102,11 @@ export class ColonyNetwork { * @remarks * Do not use this method directly but rather the class methods in the Colony or extensions * - * @param contract A ColonyJS contract - * @param method The transaction method to execute on the contract - * @param args The arguments for the method - * @param eventData A function that extracts the relevant event data from the [[ContractReceipt]] - * @param metadataType The [[MetadataType]] if the event contains metadata + * @param contract - A ColonyJS contract + * @param method - The transaction method to execute on the contract + * @param args - The arguments for the method + * @param eventData - A function that extracts the relevant event data from the [[ContractReceipt]] + * @param metadataType - The [[MetadataType]] if the event contains metadata * @returns A [[TxCreator]] */ createTxCreator< @@ -162,7 +162,7 @@ export class ColonyNetwork { * })(); * ``` * - * @param metadata The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [[ColonyMetadata]] 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]] that can upload and pin to IPFS (like the [[PinataAdapter]]). See its documentation for more information. + * @param metadata - The team metadata you would like to add (or an IPFS CID pointing to valid metadata). If [[ColonyMetadata]] 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]] that can upload and pin to IPFS (like the [[PinataAdapter]]). See its documentation for more information. * * @returns A [[TxCreator]] * @@ -298,7 +298,7 @@ export class ColonyNetwork { * @remarks * Colony contracts are versioned. If the deployed Colony version does not match the supported version an error will be thrown * - * @param address The Colony's address + * @param address - The Colony's address * @returns A Colony abstaction instance */ async getColony(address: string): Promise { diff --git a/src/ColonyNetwork/ColonyToken.ts b/src/ColonyNetwork/ColonyToken.ts index 7893923e..01f541ad 100644 --- a/src/ColonyNetwork/ColonyToken.ts +++ b/src/ColonyNetwork/ColonyToken.ts @@ -34,7 +34,7 @@ export class ColonyToken { * @remarks * Do not use this method directly but use [[Colony.getToken]] * - * @param colony A Colony instance + * @param colony - A Colony instance * @returns A Colony Token abstaction instance */ constructor(colony: Colony, tokenLockingClient: TokenLockingClient) { @@ -91,7 +91,7 @@ export class ColonyToken { * })(); * ``` * - * @param amount Amount of the token to be minted + * @param amount - Amount of the token to be minted * * @returns A [[TxCreator]] */ @@ -122,7 +122,7 @@ export class ColonyToken { * })(); * ``` * - * @param amount Amount of the token to be approved + * @param amount - Amount of the token to be approved * * @returns A tupel of event data and contract receipt * @@ -165,7 +165,7 @@ export class ColonyToken { * })(); * ``` * - * @param amount Amount of the token to be deposited + * @param amount - Amount of the token to be deposited * * @returns A tupel of event data and contract receipt * @@ -210,7 +210,7 @@ export class ColonyToken { * })(); * ``` * - * @param amount Amount of the token to be withdrawn + * @param amount - Amount of the token to be withdrawn * * @returns A tupel of event data and contract receipt * @@ -243,7 +243,7 @@ export class ColonyToken { * * This method will show the accumulated amount that was deposited using the [[ColonyToken.deposit]] method * - * @param user The wallet address that we want to check the deposited amount of + * @param user - The wallet address that we want to check the deposited amount of * * @returns The currently deposited balance of the Colony's native token */ @@ -260,8 +260,8 @@ export class ColonyToken { * * This method will show the accumulated amount that was approved using the [[ColonyToken.approve]] method * - * @param user The wallet address that we want to check the approved amount of - * @param obligator The address that has been approved to obligate the funds. + * @param user - The wallet address that we want to check the approved amount of + * @param obligator - The address that has been approved to obligate the funds. * * @returns The currently approved balance of the Colony's native token for the obligator */ diff --git a/src/ColonyNetwork/OneTxPayment.ts b/src/ColonyNetwork/OneTxPayment.ts index bfc004db..c5327f41 100644 --- a/src/ColonyNetwork/OneTxPayment.ts +++ b/src/ColonyNetwork/OneTxPayment.ts @@ -92,10 +92,10 @@ export class OneTxPayment { * })(); * ``` * - * @param recipient Wallet address of account to send the funds to (also awarded reputation when sending the native token) - * @param amount Amount to pay in wei - * @param tokenAddress The address of the token to make the payment in. Default is the Colony's native token - * @param teamId The team to use to send the funds from. Has to have funding of at least the amount you need to send. See [[Colony.moveFundsToTeam]]. Defaults to the Colony's root team + * @param recipient - Wallet address of account to send the funds to (also awarded reputation when sending the native token) + * @param amount - Amount to pay in wei + * @param tokenAddress - The address of the token to make the payment in. Default is the Colony's native token + * @param teamId - The team to use to send the funds from. Has to have funding of at least the amount you need to send. See [[Colony.moveFundsToTeam]]. Defaults to the Colony's root team * @returns A [[TxCreator]] * * **Event data** diff --git a/src/ColonyNetwork/VotingReputation.ts b/src/ColonyNetwork/VotingReputation.ts index b56f7adf..e554755a 100644 --- a/src/ColonyNetwork/VotingReputation.ts +++ b/src/ColonyNetwork/VotingReputation.ts @@ -241,9 +241,9 @@ export class VotingReputation { * * @remarks You will usually not use this function directly, but use the `send` or `motion` functions of the [[TxCreator]] within the relevant contract. * - * @param motionDomain The domain the motion will be created in - * @param encodedAction The encoded action as a string - * @param altTarget The contract to which we send the action - 0x0 for the colony (default) + * @param motionDomain - The domain the motion will be created in + * @param encodedAction - The encoded action as a string + * @param altTarget - The contract to which we send the action - 0x0 for the colony (default) * * @returns A Motion object */ @@ -272,7 +272,7 @@ export class VotingReputation { * * @remarks Will throw if motionId does not exist * - * @param motionId The motionId to get the information for + * @param motionId - The motionId to get the information for * * @returns A Motion object */ @@ -311,7 +311,7 @@ export class VotingReputation { * * @remarks Will throw if motionId does not exist * - * @param motionId The motionId to get the state for + * @param motionId - The motionId to get the state for * * @returns The motion state */ @@ -328,8 +328,8 @@ export class VotingReputation { * * @remarks To get the missing amount for activation, call [[getRemainingStakes]] * - * @param motion A Motion struct object - * @param vote A vote for (Yay) or against (Nay) the motion + * @param motion - A Motion struct object + * @param vote - A vote for (Yay) or against (Nay) the motion * * @returns The minimum stake amount */ @@ -389,7 +389,7 @@ export class VotingReputation { /** * Get the amounts remaining for Yay/Nay sides to be activated * - * @param motionId The motionId of the motion + * @param motionId - The motionId of the motion * * @returns An object containing the remaining amounts */ @@ -427,8 +427,8 @@ export class VotingReputation { * Approve `amount` of the "activated" native tokens of a user for staking in a specific team * After a token was "activated" (approved and deposited via the native token interface) it can be used for staking motions. To stake a motion, the token amount for staking has to be approved for the domain the motion was created in. See also the example in [[VotingReputation.stakeMotion]] * - * @param amount Amount of "activated" tokens to be approved for staking - * @param teamId Team that the approved tokens can be used in for staking motions + * @param amount - Amount of "activated" tokens to be approved for staking + * @param teamId - Team that the approved tokens can be used in for staking motions * * @returns A tupel of event data and contract receipt * @@ -486,7 +486,7 @@ export class VotingReputation { * })(); * ``` * - * @param amount Amount of the token to be approved + * @param amount - Amount of the token to be approved * * @returns A tupel of event data and contract receipt * @@ -575,8 +575,8 @@ export class VotingReputation { /** * Submit a vote for a motion * - * @param motionId The motionId of the motion to be finalized - * @param vote A vote for (Yay) or against (Nay) the motion + * @param motionId - The motionId of the motion to be finalized + * @param vote - A vote for (Yay) or against (Nay) the motion * * @returns A tupel of event data and contract receipt * @@ -635,8 +635,8 @@ export class VotingReputation { * * @remarks In order for a vote to count it has to be revealed within the reveal period. Only then rewards can be paid out to the voter. * - * @param motionId The motionId of the motion to be finalized - * @param vote The vote that was cast. If not provided Colony SDK will try to find out which side was voted on (not recommended) + * @param motionId - The motionId of the motion to be finalized + * @param vote - The vote that was cast. If not provided Colony SDK will try to find out which side was voted on (not recommended) * * @returns A tupel of event data and contract receipt * @@ -713,7 +713,7 @@ export class VotingReputation { * - Voting is still in progress * - The motion was already finalized * - * @param motionId The motionId of the motion to be finalized + * @param motionId - The motionId of the motion to be finalized * * @returns A tupel of event data and contract receipt * diff --git a/src/ColonyNetwork/index.ts b/src/ColonyNetwork/index.ts index aede72f2..7a8a25b9 100644 --- a/src/ColonyNetwork/index.ts +++ b/src/ColonyNetwork/index.ts @@ -1,8 +1,3 @@ -/** - * This is a description of the ColonyNetwork module - * @module ColonyNetwork - */ - export { ColonyNetwork, ColonyNetworkOptions } from './ColonyNetwork'; export { Colony, SupportedExtension, SupportedExtensions } from './Colony'; export { ColonyToken } from './ColonyToken'; diff --git a/src/events/ColonyEventManager.ts b/src/events/ColonyEventManager.ts index 51a5cdf5..6ce07e7e 100644 --- a/src/events/ColonyEventManager.ts +++ b/src/events/ColonyEventManager.ts @@ -1,8 +1,3 @@ -/** - * This is a description of the ColonyEventManager module - * @module ColonyEventManager - */ - import { constants, providers, EventFilter } from 'ethers'; import type { Result } from 'ethers/lib/utils'; @@ -100,8 +95,8 @@ export class ColonyEventManager { * As opposed to the [[ColonyNetwork]] class, this constructor _needs_ an _ethers_ JsonRpcProvider (or a subclass of it) as it's * the only provider that supports topic filtering by multiple addresses * - * @param provider An _ethers_ `JsonRpcProvider` - * @param options Optional custom [[ColonyEventManagerOptions]] + * @param provider - An _ethers_ `JsonRpcProvider` + * @param options - Optional custom [[ColonyEventManagerOptions]] * @returns A ColonyEvents instance */ constructor( @@ -166,7 +161,7 @@ export class ColonyEventManager { * })(); * ``` * - * @param filter A [[ColonyFilter]]. [[ColonyMultiFilter]]s will not work + * @param filter - A [[ColonyFilter]]. [[ColonyMultiFilter]]s will not work * @returns An array of [[ColonyEvent]]s */ async getEvents( @@ -235,10 +230,8 @@ export class ColonyEventManager { * })(); * ``` * - * @param filters An array of [[ColonyMultiFilter]]s. Normal [[ColonyFilter]]s will not work - * @param options You can define `fromBlock` and `toBlock` only once for all the filters given - * @param options.fromBlock Starting block in which to look for this event - inclusive (default: 'latest') - * @param options.toBlock Ending block in which to look for this event - inclusive (default: 'latest') + * @param filters - An array of [[ColonyMultiFilter]]s. Normal [[ColonyFilter]]s will not work + * @param options - You can define `fromBlock` and `toBlock` only once for all the filters given (default for both is `latest`) * @returns An array of [[ColonyEvent]]s */ async getMultiEvents( @@ -337,15 +330,15 @@ export class ColonyEventManager { * ); * ``` * - * @typeParam T Needs to be a valid [[EventSource]] (i.e. from `colonyEvents.eventSources`) - * @typeParam N An event signature as defined in the _ethers_ contract's [`filters`](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters) object. + * @typeParam T - Needs to be a valid [[EventSource]] (i.e. from `colonyEvents.eventSources`) + * @typeParam N - An event signature as defined in the _ethers_ contract's [`filters`](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters) object. * See the [ColonyJS documentation](https://colony.gitbook.io/colony/colonyjs) for a list of all available contracts and events * - * @param contract A valid [[EventSource]] - * @param eventName A valid event signature from the contract's `filters` object - * @param address Address of the contract that can emit this event - * @param params Parameters to filter by for the event. Has to be indexed in the contract (see _ethers_ [Event Filters](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters)) - * @param options You can define `fromBlock` and `toBlock` only once for all the filters given + * @param contract - A valid [[EventSource]] + * @param eventName - A valid event signature from the contract's `filters` object + * @param address - Address of the contract that can emit this event + * @param params - Parameters to filter by for the event. Has to be indexed in the contract (see _ethers_ [Event Filters](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters)) + * @param options - You can define `fromBlock` and `toBlock` only once for all the filters given (default for both is `latest`) * @returns A [[ColonyFilter]] */ createFilter< @@ -409,13 +402,13 @@ export class ColonyEventManager { * ); * ``` * - * @typeParam T Needs to be a valid [[EventSource]] (i.e. from `colonyEvents.eventSources`) - * @typeParam N An event signature as defined in the _ethers_ contract's [`filters`](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters) object. + * @typeParam T - Needs to be a valid [[EventSource]] (i.e. from `colonyEvents.eventSources`) + * @typeParam N - An event signature as defined in the _ethers_ contract's [`filters`](https://docs.ethers.io/v5/api/contract/contract/#Contract--filters) object. * See the [ColonyJS documentation](https://colony.gitbook.io/colony/colonyjs) for a list of all available contracts and events * - * @param contract A valid [[EventSource]] - * @param eventNames A list of valid event signatures from the contract's `filters` object - * @param address Address of the contract that can emit this event + * @param contract - A valid [[EventSource]] + * @param eventNames - A list of valid event signatures from the contract's `filters` object + * @param address - Address of the contract that can emit this event * @returns A [[ColonyMultiFilter]] */ createMultiFilter< diff --git a/src/events/index.ts b/src/events/index.ts index 982fc02b..4e23e106 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,8 +1,3 @@ -/** - * This is a description of the events module - * @module events - */ - export { ColonyEvent, ColonyEventManager, diff --git a/src/graph/index.ts b/src/graph/index.ts index 4d27f668..b31c7b3d 100644 --- a/src/graph/index.ts +++ b/src/graph/index.ts @@ -26,7 +26,7 @@ export interface SubgraphClientOptions { * * The Colony Subgraph's schema and resolvers are kept up-to-date by the Colony team and can be explored here: [Colony Subgraph](https://thegraph.com/hosted-service/subgraph/joincolony/colony-xdai). There you can make test queries to the Colony Subgraph and explore it all the way down the rabbit hole :) * - * @param options Define configuration options to instantiate the client with + * @param options - Define configuration options to instantiate the client with * @returns A ready-to-use `urql` GraphQL client instance * * @example diff --git a/src/ipfs/IpfsAdapter.ts b/src/ipfs/IpfsAdapter.ts index 932aa840..46345f77 100644 --- a/src/ipfs/IpfsAdapter.ts +++ b/src/ipfs/IpfsAdapter.ts @@ -5,7 +5,7 @@ export default interface IpfsAdapter { /** * Should return the whole URL to an IPFS resource on the corresponding gateway (e.g. https://my-ipfs-gateway/ipfs/QmXxxxXXxxXxXxXxxxXXxxxXxXXx). * - * @param cid An IPFS hash (CID) + * @param cid - An IPFS hash (CID) * @returns The URL to an ipfs resource */ getIpfsUrl(cid: string): string; @@ -15,7 +15,7 @@ export default interface IpfsAdapter { * * @remarks This function should ideally **pin** your data on the relevant service. * - * @param jsonString JSON string to upload (and pin) to IPFS + * @param jsonString - JSON string to upload (and pin) to IPFS * @returns Promise to IPFS hash (CID) */ uploadJson(jsonString: string): Promise; From ffa25230e1df7698345660fc0a9137595446ca43 Mon Sep 17 00:00:00 2001 From: chmanie Date: Tue, 6 Dec 2022 16:52:33 +0900 Subject: [PATCH 12/12] Add colony creation guide text --- docs/guides/colony-creation.md | 94 +++++++++++++++++++++++++++++++++- examples/node/create.ts | 2 +- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/docs/guides/colony-creation.md b/docs/guides/colony-creation.md index 5c6ec32a..0179ec92 100644 --- a/docs/guides/colony-creation.md +++ b/docs/guides/colony-creation.md @@ -1,7 +1,97 @@ --- -description: A guide on how to create a colony. The deployment of a colony require a few transactions for it to be up and running and fully usable. This guide explains how to go through the whole process in Colony SDK. +description: A guide on how to create a colony programmatically. The deployment of a colony requires a handful of transactions for it to be up and running and fully usable. This guide explains how to go through the whole process using Colony SDK -sidebar_position: 0 +sidebar_position: 1 --- # Creating a colony + +Even though deploying a Colony is technically just a matter of issuing one transaction, for the colony to be properly set up and usable in the dApp, some extra steps are necessary. In this guide we'll walk you through the whole process of creating the right transactions and explain what happens on the way. + +**Keep in mind that some of these transactions are optional and depend on your specific situation.** + + +For a full example see [here](https://github.com/JoinColony/colonySDK/blob/main/examples/node/create.ts). + +:::info +These examples assume that the user executing the transactions has funds in their wallet to pay for gas. If you'd like to use gasless transactions instead, use `forceMeta()` instead of `force()`. +::: + +## Step 1 (optional) - Creating a token + +If you don't have a token contract deployed yet that you wish to use as the native token in your colony, deploying it using the Colony Network is highly recommended. That will give you a better integration and control over your token from your colony (e.g. using the `mintTokens` function on the colony). + +To deploy a token, call the `deployToken` method on `ColonyNetwork`: + +```typescript +// Create token to be used with Colony +const [{ tokenAddress }] = await colonyNetwork + .deployToken('Test token', 'TOT') + .force(); +console.info('Token address', tokenAddress); +``` + +One can specify the token name, its symbol and even its decimals (even though it's recommended to leave that at the default value). This will deploy a special ERC20 token that integrates well with Colony (e.g. it supports permissions, minting and gasless transactions out of the box). For its contract code see [here](https://github.com/JoinColony/colonyNetwork/blob/develop/contracts/metaTxToken/MetaTxToken.sol). + +## Step 2 - Deploying the colony contract + +The most important step. Here the actualy colony contract will be deployed. This happens by executing a contract method on the `ColonyNetwork` (as opposed to a deploy-transaction): + +```typescript +// Create actual colony (deploys Colony contract) +const [{ colonyAddress }] = await colonyNetwork + .createColony(tokenAddress, 'colonytestname') + .force(); +``` + +Here a label for the colony can be assigned. These are unique, so pick one that's not already taken. The `createColony` method will check that. Alternatively, the `colonyNetwork.getColonyAddress(label)` function can be used. + +**If the own token was used and no extension installation is desired we would be done here. This is not recommended though, as one will at least need the `OneTxPayment` extension to properly use Colony at this stage. + +## Step 3 - Instantiate the Colony for the first time + +Let's instantiate the colony (this is the code used to instantiate an existing colony) and the token: + +```typescript +const colony = await colonyNetwork.getColony(colonyAddress); +const token = await colony.getToken(); +``` + +## Step 4 (optional) - Deploy the token authority + +The token authority is a contract that glues the token and the colony together and makes it possible for the colony to manage and move the token. The token authority can be deployed using the `deployAuthority` method on the `Token`. After that, another transaction is needed to set the token's `authority` to the one that was just deployed. If the token does not support the `setAuthority` method, this step should be skipped. + +```typescript +// Deploy TokenAuthority +const [{ tokenAuthorityAddress }] = await token + .deployAuthority([colonyAddress]) + .force(); +// Set the token's authority to the freshly deployed one +await token.setAuthority(tokenAuthorityAddress).force(); +``` + + +## Step 5 - Install the `OneTxPayment` extension + +As mentioned earlier, this step is technically optional as well but if the colony is supposed to be used productively, a form of payment extension is needed. Currently only the `OneTxPayment` extension is supported. Install it like so: + +```typescript +const [{ extensionId, version }] = await colony + .installExtension(SupportedExtension.oneTx) + .force(); +await colony.updateExtensions(); +const [{ user, setTo, role }] = await colony + .setRoles(colony.ext.oneTx.address, [ + ColonyRole.Administration, + ColonyRole.Funding, + ]) + .force(); +``` + +Here we install the extension using the `installExtension` method. This extension is an own contract that was deployed in this transaction. To get its address, we re-initialize the extensions on the colony using `updateExtensions`. After that, `oneTx` will be available on `colony.ext`. +Finally, we assign the **Administration** and **Funding** roles of the colony's `Root` team to the extension that we just deployed. The OneTxPayment extension needs these permissions to function properly. + + +## That's it! + +We have successfully deployed a colony that can be used from the dApp as well. Explore what's possible within a colony using Colony SDK [here](../api/classes/Colony.md). diff --git a/examples/node/create.ts b/examples/node/create.ts index ddc06130..2f03b22b 100644 --- a/examples/node/create.ts +++ b/examples/node/create.ts @@ -29,7 +29,7 @@ const start = async () => { // Instantiate colony and token const colony = await colonyNetwork.getColony(colonyAddress); const token = await colony.getToken(); - // Deploy TokanAuthority + // Deploy TokenAuthority const [{ tokenAuthorityAddress }] = await token .deployAuthority([colonyAddress]) .force();