import { ContractTransaction } from 'ethers'; import { BigNumber, BigNumberish, Arrayish } from 'ethers/utils'; import { TransactionOverrides } from '../../../contracts/3'; import { ColonyRole, ROOT_DOMAIN_ID } from '../../../constants'; import { IColony as IColonyV5 } from '../../../contracts/5/IColony'; import { IColony as IColonyV6 } from '../../../contracts/6/IColony'; import { ColonyNetworkClient } from '../../ColonyNetworkClient'; import { ExtendedIColony, getPermissionProofs } from './commonExtensions'; import { ColonyExtensionsV3 } from './extensionsV3'; import { addExtensions as addExtensionsV4, ColonyExtensionsV4, ExtendedEstimateV4, } from './extensionsV4'; type ValidColony = IColonyV5 | IColonyV6; type PreviousVersionsExtensions = ExtendedIColony & ColonyExtensionsV3 & ColonyExtensionsV4; /* * Estimates */ export interface ExtendedEstimateV5 extends ExtendedEstimateV4 { emitDomainReputationPenaltyWithProofs( _domainId: BigNumberish, _user: string, _amount: BigNumberish, ): Promise; setUserRolesWithProofs( _user: string, _domainId: BigNumberish, _roles: Arrayish, ): Promise; transferStakeWithProofs( _obligator: string, _user: string, _domainId: BigNumberish, _amount: BigNumberish, _recipient: string, ): Promise; /* * We overwrite the `addDomainWithProofs` interface in order to provide * function overloads for the V5 contract */ addDomainWithProofs( _parentDomainId: BigNumberish, _metadata: string, ): Promise; /* * Need to manually add the overloaded estimate signatures since TS doesn't * pick them up from the auto-generated contract definitions file */ 'addDomain(uint256,uint256,uint256)'( _permissionDomainId: BigNumberish, _childSkillIndex: BigNumberish, _parentDomainId: BigNumberish, ): Promise; 'addDomain(uint256,uint256,uint256,string)'( _permissionDomainId: BigNumberish, _childSkillIndex: BigNumberish, _parentDomainId: BigNumberish, _metadata: string, ): Promise; editDomainWithProofs( _domainId: BigNumberish, _metadata: string, ): Promise; setExpenditureStateWithProofs( _id: BigNumberish, _storageSlot: BigNumberish, _mask: boolean[], _keys: Arrayish[], _value: Arrayish, ): Promise; } /* * Extension Methods */ export type ColonyExtensionsV5 = { emitDomainReputationPenaltyWithProofs( _domainId: BigNumberish, _user: string, _amount: BigNumberish, overrides?: TransactionOverrides, ): Promise; setUserRolesWithProofs( _user: string, _domainId: BigNumberish, _roles: Arrayish, overrides?: TransactionOverrides, ): Promise; transferStakeWithProofs( _obligator: string, _user: string, _domainId: BigNumberish, _amount: BigNumberish, _recipient: string, overrides?: TransactionOverrides, ): Promise; /* * We overwrite the `addDomainWithProofs` interface in order to provide * function overloads for the V5 contract */ addDomainWithProofs( _parentDomainId: BigNumberish, _metadata: string, overrides?: TransactionOverrides, ): Promise; editDomainWithProofs( _domainId: BigNumberish, _metadata: string, overrides?: TransactionOverrides, ): Promise; setExpenditureStateWithProofs( _id: BigNumberish, _storageSlot: BigNumberish, _mask: boolean[], _keys: Arrayish[], _value: Arrayish, overrides?: TransactionOverrides, ): Promise; estimate: T['estimate'] & ExtendedEstimateV5; } & PreviousVersionsExtensions; /* * Extension Methods */ async function emitDomainReputationPenaltyWithProofs( this: ColonyExtensionsV5, _domainId: BigNumberish, _user: string, _amount: BigNumberish, overrides?: TransactionOverrides, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Arbitration, ); return this.emitDomainReputationPenalty( permissionDomainId, childSkillIndex, _domainId, _user, _amount, overrides, ); } async function setUserRolesWithProofs( this: ColonyExtensionsV5, _user: string, _domainId: BigNumberish, _roles: Arrayish, overrides?: TransactionOverrides, ): Promise { const isRootDomain = _domainId === ROOT_DOMAIN_ID.toString(); const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, isRootDomain ? ColonyRole.Root : ColonyRole.Architecture, ); return this.setUserRoles( permissionDomainId, childSkillIndex, _user, _domainId, _roles, overrides, ); } async function transferStakeWithProofs( this: ColonyExtensionsV5, _obligator: string, _user: string, _domainId: BigNumberish, _amount: BigNumberish, _recipient: string, overrides?: TransactionOverrides, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Arbitration, ); return this.transferStake( permissionDomainId, childSkillIndex, _obligator, _user, _domainId, _amount, _recipient, overrides, ); } async function addDomainWithProofs( this: ColonyExtensionsV5, _parentDomainId: BigNumberish, _metadata: string, overrides?: TransactionOverrides, ): Promise { let overrideOverload = overrides; const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _parentDomainId, ColonyRole.Architecture, ); /* * Otherwise, because of the positioning of `overrides`, it might get confused * with it */ if (typeof _metadata === 'string') { return this['addDomain(uint256,uint256,uint256,string)']( permissionDomainId, childSkillIndex, _parentDomainId, _metadata, overrideOverload, ); } /* * Since we're not calling the overloaded version, which has the metadata string, * the `_metadata` argument now stands place for the `overrides` and contains * it's values */ overrideOverload = _metadata; return this['addDomain(uint256,uint256,uint256)']( permissionDomainId, childSkillIndex, _parentDomainId, overrideOverload, ); } async function editDomainWithProofs( this: ColonyExtensionsV5, _domainId: BigNumberish, _metadata: string, overrides?: TransactionOverrides, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Architecture, ); return this.editDomain( permissionDomainId, childSkillIndex, _domainId, _metadata, overrides, ); } async function setExpenditureStateWithProofs( this: ColonyExtensionsV5, _id: BigNumberish, _storageSlot: BigNumberish, _mask: boolean[], _keys: Arrayish[], _value: Arrayish, overrides?: TransactionOverrides, ): Promise { const { domainId } = await this.getExpenditure(_id); const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, domainId, ColonyRole.Arbitration, ); return this.setExpenditureState( permissionDomainId, childSkillIndex, _id, _storageSlot, _mask, _keys, _value, overrides, ); } /* * Estimates */ async function estimateEmitDomainReputationPenaltyWithProofs( this: ColonyExtensionsV5, _domainId: BigNumberish, _user: string, _amount: BigNumberish, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Arbitration, ); return this.estimate.emitDomainReputationPenalty( permissionDomainId, childSkillIndex, _domainId, _user, _amount, ); } async function estimateSetUserRolesWithProofs( this: ColonyExtensionsV5, _user: string, _domainId: BigNumberish, _roles: Arrayish, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Arbitration, ); return this.estimate.setUserRoles( permissionDomainId, childSkillIndex, _user, _domainId, _roles, ); } async function estimateTransferStakeWithProofs( this: ColonyExtensionsV5, _obligator: string, _user: string, _domainId: BigNumberish, _amount: BigNumberish, _recipient: string, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Arbitration, ); return this.estimate.transferStake( permissionDomainId, childSkillIndex, _obligator, _user, _domainId, _amount, _recipient, ); } async function estimateAddDomainWithProofs( this: ColonyExtensionsV5, _parentDomainId: BigNumberish, _metadata: string, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _parentDomainId, ColonyRole.Architecture, ); if (_metadata) { return this.estimate['addDomain(uint256,uint256,uint256,string)']( permissionDomainId, childSkillIndex, _parentDomainId, _metadata, ); } return this.estimate['addDomain(uint256,uint256,uint256)']( permissionDomainId, childSkillIndex, _parentDomainId, ); } async function estimateEditDomainWithProofs( this: ColonyExtensionsV5, _domainId: BigNumberish, _metadata: string, ): Promise { const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, _domainId, ColonyRole.Architecture, ); return this.estimate.editDomain( permissionDomainId, childSkillIndex, _domainId, _metadata, ); } async function estimateSetExpenditureStateWithProofs( this: ColonyExtensionsV5, _id: BigNumberish, _storageSlot: BigNumberish, _mask: boolean[], _keys: Arrayish[], _value: Arrayish, ): Promise { const { domainId } = await this.getExpenditure(_id); const [permissionDomainId, childSkillIndex] = await getPermissionProofs( this, domainId, ColonyRole.Arbitration, ); return this.estimate.setExpenditureState( permissionDomainId, childSkillIndex, _id, _storageSlot, _mask, _keys, _value, ); } /* * Bindings */ export const addExtensions = ( instance: ExtendedIColony, networkClient: ColonyNetworkClient, ): ColonyExtensionsV5 => { // Add all extensions from v4, because these are also still valid const extendedInstance = addExtensionsV4( instance, networkClient, ) as ColonyExtensionsV5; /* eslint-disable max-len */ extendedInstance.emitDomainReputationPenaltyWithProofs = emitDomainReputationPenaltyWithProofs.bind( extendedInstance, ); extendedInstance.setUserRolesWithProofs = setUserRolesWithProofs.bind( extendedInstance, ); extendedInstance.transferStakeWithProofs = transferStakeWithProofs.bind( extendedInstance, ); /* * We basically disable the signature type of the initial (pre V3) method * * This is because we overload the method, but not in a way that TS likes, as we * add the overloaded argument in the middle, and not at the end. */ (extendedInstance.addDomainWithProofs as unknown) = addDomainWithProofs.bind( extendedInstance, ); extendedInstance.editDomainWithProofs = editDomainWithProofs.bind( extendedInstance, ); extendedInstance.setExpenditureStateWithProofs = setExpenditureStateWithProofs.bind( extendedInstance, ); extendedInstance.estimate.emitDomainReputationPenaltyWithProofs = estimateEmitDomainReputationPenaltyWithProofs.bind( extendedInstance, ); extendedInstance.estimate.setUserRolesWithProofs = estimateSetUserRolesWithProofs.bind( extendedInstance, ); extendedInstance.estimate.transferStakeWithProofs = estimateTransferStakeWithProofs.bind( extendedInstance, ); /* * We basically disable the signature type of the initial (pre V3) method * * This is because we overload the method, but not in a way that TS likes, as we * add the overloaded argument in the middle, and not at the end. */ (extendedInstance.estimate .addDomainWithProofs as unknown) = estimateAddDomainWithProofs.bind( extendedInstance, ); extendedInstance.estimate.editDomainWithProofs = estimateEditDomainWithProofs.bind( extendedInstance, ); extendedInstance.estimate.setExpenditureStateWithProofs = estimateSetExpenditureStateWithProofs.bind( extendedInstance, ); /* eslint-enable max-len */ return extendedInstance; };