diff --git a/configs/src/deployments/contracts.ts b/configs/src/deployments/contracts.ts new file mode 100644 index 00000000..031b02c7 --- /dev/null +++ b/configs/src/deployments/contracts.ts @@ -0,0 +1,46 @@ +import {SupportedNetworks} from '../networks'; +import * as arbitrum from './json/arbitrum.json'; +import * as arbitrumSepolia from './json/arbitrumSepolia.json'; +import * as baseGoerli from './json/baseGoerli.json'; +import * as baseMainnet from './json/baseMainnet.json'; +import * as baseSepolia from './json/baseSepolia.json'; +import * as goerli from './json/goerli.json'; +import * as mainnet from './json/mainnet.json'; +import * as mumbai from './json/mumbai.json'; +import * as polygon from './json/polygon.json'; +import * as sepolia from './json/sepolia.json'; +import {NetworkDeployment, SupportedVersions} from './types'; + +export { + mainnet, + goerli, + sepolia, + polygon, + mumbai, + baseMainnet, + baseGoerli, + baseSepolia, + arbitrum, + arbitrumSepolia, +}; + +export const contracts: { + [network in SupportedNetworks]: { + [version in SupportedVersions]?: NetworkDeployment; + }; +} = { + mainnet, + goerli, + sepolia, + polygon, + mumbai, + baseMainnet, + baseGoerli, + baseSepolia, + arbitrum, + arbitrumSepolia, + local: { + [SupportedVersions.V1_0_0]: {} as NetworkDeployment, + [SupportedVersions.V1_3_0]: {} as NetworkDeployment, + }, +}; diff --git a/configs/src/deployments/getters.ts b/configs/src/deployments/getters.ts new file mode 100644 index 00000000..30432b52 --- /dev/null +++ b/configs/src/deployments/getters.ts @@ -0,0 +1,52 @@ +import {SupportedNetworks} from '../networks'; +import {contracts} from './contracts'; +import { + NetworkDeployment, + NetworkDeployments, + SupportedVersions, +} from './types'; + +/** + * Retrieves the network deployments based on the specified network. + * + * @param {SupportedNetworks} network - The network to retrieve the deployments for. + * @return {NetworkDeployments} The network deployments for the specified network. + */ +export function getNetworkDeployments( + network: SupportedNetworks +): NetworkDeployments { + return contracts[network]; +} + +/** + * Retrieves the network deployment for a specific version. + * + * @param {SupportedNetworks} network - The network to retrieve the deployment for. + * @param {SupportedVersions} version - The version of the deployment. + * @return {NetworkDeployment | null} The network deployment for the specified version, or null if not found. + */ +export function getNetworkDeploymentForVersion( + network: SupportedNetworks, + version: SupportedVersions +): NetworkDeployment | null { + return getNetworkDeployments(network)[version] || null; +} + +/** + * Retrieves the latest network deployment for the specified network. + * + * @param {SupportedNetworks} network - The network to retrieve the deployment for. + * @return {NetworkDeployment | null} The latest network deployment, or null if not found. + */ +export function getLatestNetworkDeployment( + network: SupportedNetworks +): NetworkDeployment | null { + const versions = Object.values(SupportedVersions).reverse(); + for (const version of versions) { + const deployment = getNetworkDeploymentForVersion(network, version); + if (deployment) { + return deployment; + } + } + return null; +} diff --git a/configs/src/deployments/index.ts b/configs/src/deployments/index.ts index 2d97db42..98551508 100644 --- a/configs/src/deployments/index.ts +++ b/configs/src/deployments/index.ts @@ -1,96 +1,3 @@ -import { - NetworkDeployment, - NetworkDeployments, - SupportedNetworks, - SupportedVersions, -} from '../types'; -import * as arbitrum from './arbitrum.json'; -import * as arbitrumSepolia from './arbitrumSepolia.json'; -import * as baseGoerli from './baseGoerli.json'; -import * as baseMainnet from './baseMainnet.json'; -import * as baseSepolia from './baseSepolia.json'; -import * as goerli from './goerli.json'; -import * as mainnet from './mainnet.json'; -import * as mumbai from './mumbai.json'; -import * as polygon from './polygon.json'; -import * as sepolia from './sepolia.json'; - -const contracts: { - [network in SupportedNetworks]: { - [version in SupportedVersions]?: NetworkDeployment; - }; -} = { - mainnet, - goerli, - sepolia, - polygon, - mumbai, - baseMainnet, - baseGoerli, - baseSepolia, - arbitrum, - arbitrumSepolia, - local: { - [SupportedVersions.V1_0_0]: {} as NetworkDeployment, - [SupportedVersions.V1_3_0]: {} as NetworkDeployment, - }, -}; - -/** - * Retrieves the network deployments based on the specified network. - * - * @param {SupportedNetworks} network - The network to retrieve the deployments for. - * @return {NetworkDeployments} The network deployments for the specified network. - */ -export function getNetworkDeployments( - network: SupportedNetworks -): NetworkDeployments { - return contracts[network]; -} - -/** - * Retrieves the network deployment for a specific version. - * - * @param {SupportedNetworks} network - The network to retrieve the deployment for. - * @param {SupportedVersions} version - The version of the deployment. - * @return {NetworkDeployment | null} The network deployment for the specified version, or null if not found. - */ -export function getNetworkDeploymentForVersion( - network: SupportedNetworks, - version: SupportedVersions -): NetworkDeployment | null { - return getNetworkDeployments(network)[version] || null; -} - -/** - * Retrieves the latest network deployment for the specified network. - * - * @param {SupportedNetworks} network - The network to retrieve the deployment for. - * @return {NetworkDeployment | null} The latest network deployment, or null if not found. - */ -export function getLatestNetworkDeployment( - network: SupportedNetworks -): NetworkDeployment | null { - const versions = Object.values(SupportedVersions).reverse(); - for (const version of versions) { - const deployment = getNetworkDeploymentForVersion(network, version); - if (deployment) { - return deployment; - } - } - return null; -} - -export { - contracts, - mainnet, - goerli, - sepolia, - polygon, - mumbai, - baseMainnet, - baseGoerli, - baseSepolia, - arbitrum, - arbitrumSepolia, -}; +export * from './types'; +export * from './getters'; +export * from './contracts'; diff --git a/configs/src/deployments/arbitrum.json b/configs/src/deployments/json/arbitrum.json similarity index 100% rename from configs/src/deployments/arbitrum.json rename to configs/src/deployments/json/arbitrum.json diff --git a/configs/src/deployments/arbitrumSepolia.json b/configs/src/deployments/json/arbitrumSepolia.json similarity index 100% rename from configs/src/deployments/arbitrumSepolia.json rename to configs/src/deployments/json/arbitrumSepolia.json diff --git a/configs/src/deployments/baseGoerli.json b/configs/src/deployments/json/baseGoerli.json similarity index 100% rename from configs/src/deployments/baseGoerli.json rename to configs/src/deployments/json/baseGoerli.json diff --git a/configs/src/deployments/baseMainnet.json b/configs/src/deployments/json/baseMainnet.json similarity index 100% rename from configs/src/deployments/baseMainnet.json rename to configs/src/deployments/json/baseMainnet.json diff --git a/configs/src/deployments/baseSepolia.json b/configs/src/deployments/json/baseSepolia.json similarity index 100% rename from configs/src/deployments/baseSepolia.json rename to configs/src/deployments/json/baseSepolia.json diff --git a/configs/src/deployments/goerli.json b/configs/src/deployments/json/goerli.json similarity index 100% rename from configs/src/deployments/goerli.json rename to configs/src/deployments/json/goerli.json diff --git a/configs/src/deployments/mainnet.json b/configs/src/deployments/json/mainnet.json similarity index 100% rename from configs/src/deployments/mainnet.json rename to configs/src/deployments/json/mainnet.json diff --git a/configs/src/deployments/mumbai.json b/configs/src/deployments/json/mumbai.json similarity index 100% rename from configs/src/deployments/mumbai.json rename to configs/src/deployments/json/mumbai.json diff --git a/configs/src/deployments/polygon.json b/configs/src/deployments/json/polygon.json similarity index 100% rename from configs/src/deployments/polygon.json rename to configs/src/deployments/json/polygon.json diff --git a/configs/src/deployments/sepolia.json b/configs/src/deployments/json/sepolia.json similarity index 100% rename from configs/src/deployments/sepolia.json rename to configs/src/deployments/json/sepolia.json diff --git a/configs/src/types.ts b/configs/src/deployments/types.ts similarity index 77% rename from configs/src/types.ts rename to configs/src/deployments/types.ts index 4bd47279..fae16a3d 100644 --- a/configs/src/types.ts +++ b/configs/src/deployments/types.ts @@ -1,41 +1,3 @@ -export type NetworkConfig = { - url: string; - isTestnet: boolean; - chainId: number; - name: SupportedNetworks; - feesUrl?: string; - gasPrice?: number; - aliases: NetworkAliases; -}; - -export type NetworkAliases = { - [index in SupportedAliases]?: string; -}; - -export type NetworkConfigs = { - [network in SupportedNetworks]: T; -}; - -export enum SupportedAliases { - ETHERS_5 = 'ethers5', - ETHERS_6 = 'ethers6', - ALCHEMY_SUBGRAPHS = 'alchemySubgraphs', -} - -export enum SupportedNetworks { - MAINNET = 'mainnet', - GOERLI = 'goerli', - SEPOLIA = 'sepolia', - POLYGON = 'polygon', - MUMBAI = 'mumbai', - BASE = 'baseMainnet', - BASE_GOERLI = 'baseGoerli', - BASE_SEPOLIA = 'baseSepolia', - ARBITRUM = 'arbitrum', - ARBITRUM_SEPOLIA = 'arbitrumSepolia', - LOCAL = 'local', -} - // the entries in this enum has to be in order from // oldest to newest so that getLatestNetworkVersion() works as expected export enum SupportedVersions { diff --git a/configs/src/index.ts b/configs/src/index.ts index 48e54ee3..188d6a8b 100644 --- a/configs/src/index.ts +++ b/configs/src/index.ts @@ -1,3 +1,2 @@ export * from './networks'; -export * from './types'; -export * from './deployments/index'; +export * from './deployments'; diff --git a/configs/src/networks/getters.ts b/configs/src/networks/getters.ts new file mode 100644 index 00000000..4b2c5a5d --- /dev/null +++ b/configs/src/networks/getters.ts @@ -0,0 +1,87 @@ +import {networks} from './networks'; +import {NetworkConfig, SupportedAliases, SupportedNetworks} from './types'; + +/** + * Retrieves the network configuration for a given supported network. + * + * @param {SupportedNetworks} network - The supported network to retrieve the configuration for. + * @return {NetworkConfig | null} The network configuration if it exists, otherwise null. + */ +export function getNetwork(network: SupportedNetworks): NetworkConfig | null { + if (networks[network]) { + return networks[network]; + } + + return null; +} + +export function getNetworkByChainId(chainId: number): NetworkConfig | null { + return ( + Object.values(networks).find(network => network.chainId === chainId) || null + ); +} + +/** + * Retrieves the network configuration object by name or alias. + * + * @param {string | SupportedNetworks} network - The name or alias of the network. + * @return {NetworkConfig | null} The network configuration object if found, or `null` if not found. + */ +export function getNetworkByNameOrAlias( + network: string | SupportedNetworks +): NetworkConfig | null { + const networkConfig = + getNetworkByAlias(network) || getNetwork(network as SupportedNetworks); + if (networkConfig) { + return networkConfig; + } + return null; +} + +/** + * Retrieves the network configuration object based on the given alias. + * + * @param {string} alias - The alias of the network. + * @return {NetworkConfig | null} The network configuration object corresponding to the alias, or null if not found. + */ +export function getNetworkByAlias(alias: string): NetworkConfig | null { + const networkName = getNetworkNameByAlias(alias); + if (networkName) { + return getNetwork(networkName); + } + return null; +} + +/** + * Retrieves the network name by its alias. If the name is already supported it returns the alias back as name + * + * @param {string} alias - The alias of the network. + * @return {SupportedNetworks | null} The network name corresponding to the alias, or null if no match is found. + */ +export function getNetworkNameByAlias(alias: string): SupportedNetworks | null { + if (Object.values(SupportedNetworks).includes(alias as SupportedNetworks)) { + return alias as SupportedNetworks; + } + + for (const networkName of Object.values(SupportedNetworks)) { + const network = getNetwork(networkName); + if (network) { + const aliases = Object.values(network.aliases); + if (aliases.includes(alias)) { + return networkName; + } + } + } + return null; +} + +export function getNetworkAlias( + aliasName: SupportedAliases, + network: SupportedNetworks +): string | null { + const networkConfig = getNetwork(network); + if (!networkConfig) { + return null; + } + return networkConfig.aliases[aliasName] || network; +} diff --git a/configs/src/networks/index.ts b/configs/src/networks/index.ts new file mode 100644 index 00000000..fcb073fe --- /dev/null +++ b/configs/src/networks/index.ts @@ -0,0 +1 @@ +export * from './types'; diff --git a/configs/src/networks.ts b/configs/src/networks/networks.ts similarity index 51% rename from configs/src/networks.ts rename to configs/src/networks/networks.ts index 65e4bb93..a090aa44 100644 --- a/configs/src/networks.ts +++ b/configs/src/networks/networks.ts @@ -1,94 +1,4 @@ -import { - NetworkConfig, - NetworkConfigs, - SupportedAliases, - SupportedNetworks, -} from './types'; - -/** - * Retrieves the network configuration for a given supported network. - * - * @param {SupportedNetworks} network - The supported network to retrieve the configuration for. - * @return {NetworkConfig | null} The network configuration if it exists, otherwise null. - */ -export function getNetwork(network: SupportedNetworks): NetworkConfig | null { - if (networks[network]) { - return networks[network]; - } - - return null; -} - -export function getNetworkByChainId(chainId: number): NetworkConfig | null { - return ( - Object.values(networks).find(network => network.chainId === chainId) || null - ); -} - -/** - * Retrieves the network configuration object by name or alias. - * - * @param {string | SupportedNetworks} network - The name or alias of the network. - * @return {NetworkConfig | null} The network configuration object if found, or `null` if not found. - */ -export function getNetworkByNameOrAlias( - network: string | SupportedNetworks -): NetworkConfig | null { - const networkConfig = - getNetworkByAlias(network) || getNetwork(network as SupportedNetworks); - if (networkConfig) { - return networkConfig; - } - return null; -} - -/** - * Retrieves the network configuration object based on the given alias. - * - * @param {string} alias - The alias of the network. - * @return {NetworkConfig | null} The network configuration object corresponding to the alias, or null if not found. - */ -export function getNetworkByAlias(alias: string): NetworkConfig | null { - const networkName = getNetworkNameByAlias(alias); - if (networkName) { - return getNetwork(networkName); - } - return null; -} - -/** - * Retrieves the network name by its alias. If the name is already supported it returns the alias back as name - * - * @param {string} alias - The alias of the network. - * @return {SupportedNetworks | null} The network name corresponding to the alias, or null if no match is found. - */ -export function getNetworkNameByAlias(alias: string): SupportedNetworks | null { - if (Object.values(SupportedNetworks).includes(alias as SupportedNetworks)) { - return alias as SupportedNetworks; - } - - for (const networkName of Object.values(SupportedNetworks)) { - const network = getNetwork(networkName); - if (network) { - const aliases = Object.values(network.aliases); - if (aliases.includes(alias)) { - return networkName; - } - } - } - return null; -} - -export function getNetworkAlias( - aliasName: SupportedAliases, - network: SupportedNetworks -): string | null { - const networkConfig = getNetwork(network); - if (!networkConfig) { - return null; - } - return networkConfig.aliases[aliasName] || network; -} +import {NetworkConfigs, SupportedNetworks} from './types'; export const networks: NetworkConfigs = { [SupportedNetworks.MAINNET]: { diff --git a/configs/src/networks/types.ts b/configs/src/networks/types.ts new file mode 100644 index 00000000..d6989923 --- /dev/null +++ b/configs/src/networks/types.ts @@ -0,0 +1,37 @@ +export enum SupportedAliases { + ETHERS_5 = 'ethers5', + ETHERS_6 = 'ethers6', + ALCHEMY_SUBGRAPHS = 'alchemySubgraphs', +} + +export enum SupportedNetworks { + MAINNET = 'mainnet', + GOERLI = 'goerli', + SEPOLIA = 'sepolia', + POLYGON = 'polygon', + MUMBAI = 'mumbai', + BASE = 'baseMainnet', + BASE_GOERLI = 'baseGoerli', + BASE_SEPOLIA = 'baseSepolia', + ARBITRUM = 'arbitrum', + ARBITRUM_SEPOLIA = 'arbitrumSepolia', + LOCAL = 'local', +} + +export type NetworkConfig = { + url: string; + isTestnet: boolean; + chainId: number; + name: SupportedNetworks; + feesUrl?: string; + gasPrice?: number; + aliases: NetworkAliases; +}; + +export type NetworkAliases = { + [index in SupportedAliases]?: string; +}; + +export type NetworkConfigs = { + [network in SupportedNetworks]: NetworkConfig; +}; diff --git a/configs/src/test/unit/deployments.test.ts b/configs/src/test/unit/deployments.test.ts index 33a75a62..1faaa86b 100644 --- a/configs/src/test/unit/deployments.test.ts +++ b/configs/src/test/unit/deployments.test.ts @@ -1,10 +1,11 @@ import { + SupportedVersions, contracts, getLatestNetworkDeployment, getNetworkDeploymentForVersion, getNetworkDeployments, } from '../../deployments'; -import {SupportedNetworks, SupportedVersions} from '../../types'; +import {SupportedNetworks} from '../../networks'; describe('Deployments', () => { describe('getNetworkDeployments', () => { diff --git a/configs/src/test/unit/networks.test.ts b/configs/src/test/unit/networks.test.ts index 7eca8927..0c62653a 100644 --- a/configs/src/test/unit/networks.test.ts +++ b/configs/src/test/unit/networks.test.ts @@ -1,3 +1,8 @@ +import { + NetworkConfig, + SupportedAliases, + SupportedNetworks, +} from '../../networks'; import { getNetwork, getNetworkAlias, @@ -5,9 +10,8 @@ import { getNetworkByChainId, getNetworkByNameOrAlias, getNetworkNameByAlias, - networks, -} from '../../networks'; -import {NetworkConfig, SupportedAliases, SupportedNetworks} from '../../types'; +} from '../../networks/getters'; +import {networks} from '../../networks/networks'; describe('Deployments', () => { describe('getNetwork', () => { diff --git a/sdk/src/bitmap.ts b/sdk/src/bitmap.ts deleted file mode 100644 index f0f6e1b3..00000000 --- a/sdk/src/bitmap.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {BigNumber} from 'ethers'; - -export function flipBit(index: number, num: BigNumber): BigNumber { - const mask = BigNumber.from(1).shl(index & 0xff); - return num.xor(mask); -} - -export function getBit(index: number, num: BigNumber): boolean { - const mask = BigNumber.from(1).shl(index & 0xff); - return !num.and(mask).eq(0); -} diff --git a/sdk/src/bitmap/errors.ts b/sdk/src/bitmap/errors.ts new file mode 100644 index 00000000..8a9de0c6 --- /dev/null +++ b/sdk/src/bitmap/errors.ts @@ -0,0 +1,13 @@ +import {SdkError} from '../errors'; + +export class InvalidArraySizeError extends SdkError { + constructor(size: number, cause?: any) { + super(`Invalid array size: ${size}`, cause); + } +} + +export class InvalidBitMapValueError extends SdkError { + constructor(cause?: any) { + super('The bitmap value is too big', cause); + } +} diff --git a/sdk/src/bitmap/index.ts b/sdk/src/bitmap/index.ts new file mode 100644 index 00000000..ee262b44 --- /dev/null +++ b/sdk/src/bitmap/index.ts @@ -0,0 +1,2 @@ +export * from './utils'; +export * from './errors'; diff --git a/sdk/src/bitmap/utils.ts b/sdk/src/bitmap/utils.ts new file mode 100644 index 00000000..0942859b --- /dev/null +++ b/sdk/src/bitmap/utils.ts @@ -0,0 +1,67 @@ +import {InvalidArraySizeError, InvalidBitMapValueError} from './errors'; +import {BigNumber} from 'ethers'; + +/** + * Flips a specific bit in a `BigNumber` object and returns a new `BigNumber` object with the bit flipped. + * + * @export + * @param {number} index + * @param {BigNumber} num + * @return {*} {BigNumber} + */ +export function flipBit(index: number, num: BigNumber): BigNumber { + const mask = BigNumber.from(1).shl(index & 0xff); + return num.xor(mask); +} + +/** + * Checks if a specific bit is set in a `BigNumber` object and returns `true` if the bit is set and `false` if it's not. + * + * @export + * @param {number} index + * @param {BigNumber} num + * @return {*} {boolean} + */ +export function getBit(index: number, num: BigNumber): boolean { + const mask = BigNumber.from(1).shl(index & 0xff); + return !num.and(mask).eq(0); +} + +/** + * Transforms a bigint into an array of booleans + * + * @param {bigint} bitmap + * @return {*} {Array} + */ +export function bitmapToBoolArray(bitmap: bigint): Array { + if (bitmap >= BigInt(1) << BigInt(256)) { + throw new InvalidBitMapValueError(); + } + + const result: Array = []; + for (let i = 0; i < 256; i++) { + const mask = BigInt(1) << BigInt(i); + result.push((bitmap & mask) != BigInt(0)); + } + + return result; +} + +/** + * Transforms an array of booleans into a bitmap big integer + * + * @export + * @param {Array} [bools] + * @return {*} + */ +export function boolArrayToBitmap(bools?: Array) { + if (!bools || !bools.length) return BigInt(0); + else if (bools.length > 256) throw new InvalidArraySizeError(bools.length); + + let result = BigInt(0); + for (let i = 0; i < 256; i++) { + if (!bools[i]) continue; + result |= BigInt(1) << BigInt(i); + } + return result; +} diff --git a/sdk/src/encoding.ts b/sdk/src/encoding.ts index 38ffa979..fdf237a5 100644 --- a/sdk/src/encoding.ts +++ b/sdk/src/encoding.ts @@ -1,7 +1,5 @@ import {HEX_STRING_REGEX, OSX_PROPOSAL_ID_REGEX} from './constants'; import { - InvalidArraySizeError, - InvalidBitMapValueError, InvalidDigitsValueError, InvalidProposalIdError, InvalidRatioValueError, @@ -153,45 +151,7 @@ export function decodeProposalId(proposalId: string): { }; } -/** - * Transforms an array of booleans into a bitmap big integer - * - * @export - * @param {Array} [bools] - * @return {*} - */ -export function boolArrayToBitmap(bools?: Array) { - if (!bools || !bools.length) return BigInt(0); - else if (bools.length > 256) throw new InvalidArraySizeError(bools.length); - - let result = BigInt(0); - for (let i = 0; i < 256; i++) { - if (!bools[i]) continue; - result |= BigInt(1) << BigInt(i); - } - - return result; -} -/** - * Transforms a bigint into an array of booleans - * - * @param {bigint} bitmap - * @return {*} {Array} - */ -export function bitmapToBoolArray(bitmap: bigint): Array { - if (bitmap >= BigInt(1) << BigInt(256)) { - throw new InvalidBitMapValueError(); - } - - const result: Array = []; - for (let i = 0; i < 256; i++) { - const mask = BigInt(1) << BigInt(i); - result.push((bitmap & mask) != BigInt(0)); - } - - return result; -} /** * Gets the extended version of a proposal id from the compact one diff --git a/sdk/src/errors.ts b/sdk/src/errors.ts index 0da2c3e9..fec17e56 100644 --- a/sdk/src/errors.ts +++ b/sdk/src/errors.ts @@ -1,6 +1,5 @@ -import {ContractTransaction} from '@ethersproject/contracts'; -class SdkError extends Error { +export class SdkError extends Error { public cause?: Error | string; constructor(message: string, cause?: any) { super(message); @@ -300,11 +299,6 @@ export class ProposalNotFoundError extends SdkError { } } -export class InvalidArraySizeError extends SdkError { - constructor(size: number, cause?: any) { - super(`Invalid array size: ${size}`, cause); - } -} export class InvalidRatioValueError extends SdkError { constructor(ratio: number, cause?: any) { @@ -329,13 +323,6 @@ export class ValueOutOfRangeError extends SdkError { super(`The value is out of range`, cause); } } - -export class InvalidBitMapValueError extends SdkError { - constructor(cause?: any) { - super('The bitmap value is too big', cause); - } -} - export class EmptyMultiUriError extends SdkError { constructor(cause?: any) { super('The multi URI is empty', cause); @@ -359,12 +346,3 @@ export class InvalidPermissionOperationType extends SdkError { super('Invalid permission operation', cause); } } - -export class EventNotFoundError extends SdkError { - constructor(eventName: string, tx: ContractTransaction) { - super( - `Event "${eventName}" could not be found in transaction ${tx.hash}.`, - tx - ); - } -} diff --git a/sdk/src/events.ts b/sdk/src/events.ts deleted file mode 100644 index f43d5b07..00000000 --- a/sdk/src/events.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {EventNotFoundError} from './errors'; -import {ContractTransaction} from 'ethers'; -import {Interface, LogDescription} from 'ethers/lib/utils'; - -/** - * Finds a typed event in transaction given the event name - * - * @export - * @param {ContractReceipt} tx - * @param {string} eventName - * @return {*} {(T)} - */ -export async function findEvent(tx: ContractTransaction, eventName: string) { - const receipt = await tx.wait(); - - const event = (receipt.events || []).find(event => event.event === eventName); - - if (!event) { - throw new EventNotFoundError(eventName, tx); - } - - return event as T; -} - -/** - * Finds a log in a transaction given the interface of the emitting contract and the event name - * - * @export - * @param {ContractTransaction} tx - * @param {Interface} iface - * @param {string} eventName - * @return {*} {(LogDescription | undefined)} - */ -export async function findEventTopicLog( - tx: ContractTransaction, - iface: Interface, - eventName: string -): Promise { - const receipt = await tx.wait(); - const topic = iface.getEventTopic(eventName); - const log = receipt.logs.find(x => x.topics[0] === topic); - if (!log) { - throw new EventNotFoundError(eventName, tx); - } - return iface.parseLog(log) as LogDescription & (T | LogDescription); -} - -export const CALLBACK_HANDLER_EVENTS = { - CallbackReceived: 'CallbackReceived', -}; - -export const PROXY_FACTORY_EVENTS = { - ProxyCreated: 'ProxyCreated', -}; - -export const DAO_EVENTS = { - NewURI: 'NewURI', -}; - -export const DAO_REGISTRY_EVENTS = { - DAORegistered: 'DAORegistered', -}; - -export const IPROPOSAL_EVENTS = { - ProposalCreated: 'ProposalCreated', - ProposalExecuted: 'ProposalExecuted', -}; - -export const IDAO_EVENTS = { - MetadataSet: 'MetadataSet', - Executed: 'Executed', - Deposited: 'Deposited', - StandardCallbackRegistered: 'StandardCallbackRegistered', - TrustedForwarderSet: 'TrustedForwarderSet', - NewURI: 'NewURI', -}; - -export const IMEMBERSHIP_EVENTS = { - MembersAdded: 'MembersAdded', - MembersRemoved: 'MembersRemoved', - MembershipContractAnnounced: 'MembershipContractAnnounced', -}; - -export const INTERFACE_BASED_REGISTRY_EVENTS = { - Registered: 'Registered', -}; - -export const PERMISSION_MANAGER = { - Granted: 'Granted', - Revoked: 'Revoked', -}; - -export const PLUGIN_REPO_EVENTS = { - VersionCreated: 'VersionCreated', -}; - -export const PLUGIN_REPO_REGISTRY_EVENTS = { - PluginRepoRegistered: 'PluginRepoRegistered', - ReleaseMetadataUpdated: 'ReleaseMetadataUpdated', -}; - -export const PLUGIN_SETUP_PROCESSOR_EVENTS = { - InstallationPrepared: 'InstallationPrepared', - InstallationApplied: 'InstallationApplied', - UpdatePrepared: 'UpdatePrepared', - UpdateApplied: 'UpdateApplied', - UninstallationPrepared: 'UninstallationPrepared', - UninstallationApplied: 'UninstallationApplied', -}; - -export const UUPS_UPGRADEABLE_EVENTS = { - Upgraded: 'Upgraded', -}; diff --git a/sdk/src/events/errors.ts b/sdk/src/events/errors.ts new file mode 100644 index 00000000..190e0b6f --- /dev/null +++ b/sdk/src/events/errors.ts @@ -0,0 +1,11 @@ +import {SdkError} from '../errors'; +import {ContractReceipt} from '@ethersproject/contracts'; + +export class EventNotFoundError extends SdkError { + constructor(eventName: string, cr: ContractReceipt) { + super( + `Event "${eventName}" could not be found in transaction ${cr.transactionHash}.`, + cr + ); + } +} diff --git a/sdk/src/events/events.ts b/sdk/src/events/events.ts new file mode 100644 index 00000000..7aac3c78 --- /dev/null +++ b/sdk/src/events/events.ts @@ -0,0 +1,67 @@ +export enum CallbackHandlerEvents { + CALLBACK_RECEIVED = 'CallbackReceived', +} + +export enum ProxyFactoryEvents { + PROXY_CREATED = 'ProxyCreated', +} + +export enum DaoEvents { + NEW_URI = 'NewURI', +} + +export enum DaoRegistryEvents { + DAO_REGISTERED = 'DAORegistered', +} + +export enum IProposalEvents { + PROPOSAL_CREATED = 'ProposalCreated', + PROPOSAL_EXECUTED = 'ProposalExecuted', +} + +export enum IDaoEvents { + METADATA_SET = 'MetadataSet', + EXECUTED = 'Executed', + DEPOSITED = 'Deposited', + STANDARD_CALLBACK_REGISTERED = 'StandardCallbackRegistered', + TRUSTED_FORWARDER_SET = 'TrustedForwarderSet', + NEW_URI = 'NewURI', +} + +export enum IMembershipEvents { + MEMBERS_ADDED = 'MembersAdded', + MEMBERS_REMOVED = 'MembersRemoved', + MEMBERSHIP_CONTRACT_ANNOUNCED = 'MembershipContractAnnounced', +} + +export enum InterfaceBasedRegistryEvents { + REGISTERED = 'Registered', +} + +export enum PermissionManagerEvents { + GRANTED = 'Granted', + REVOKED = 'Revoked', +} + +export enum PluginRepoEvents { + VERSION_CREATED = 'VersionCreated', +} + +export enum PluginRepoRegistryEvents { + PLUGIN_REPO_REGISTERED = 'PluginRepoRegistered', + RELEASE_METADATA_UPDATED = 'ReleaseMetadataUpdated', +} + +export enum PluginSetupProcessorEvents { + INSTALLATION_PREPARED = 'InstallationPrepared', + INSTALLATION_APPLIED = 'InstallationApplied', + UPDATE_PREPARED = 'UpdatePrepared', + UPDATE_APPLIED = 'UpdateApplied', + UNINSTALLATION_PREPARED = 'UninstallationPrepared', + UNINSTALLATION_APPLIED = 'UninstallationApplied', +} + +export enum UupsUpgradableEvents { + UPGRADED = 'Upgraded', +} + diff --git a/sdk/src/events/index.ts b/sdk/src/events/index.ts new file mode 100644 index 00000000..8046cf1b --- /dev/null +++ b/sdk/src/events/index.ts @@ -0,0 +1,3 @@ +export * from './utils'; +export * from './errors'; +export * from './events'; \ No newline at end of file diff --git a/sdk/src/events/utils.test.ts b/sdk/src/events/utils.test.ts new file mode 100644 index 00000000..3ad8a771 --- /dev/null +++ b/sdk/src/events/utils.test.ts @@ -0,0 +1,54 @@ +import { findEventTopicLog } from './utils'; +import { ContractReceipt, Interface, LogDescription } from 'ethers'; + +describe('findEventTopicLog', () => { + const cr: ContractReceipt = { + logs: [ + { + topics: ['0x1234567890'], + data: '0x', + blockNumber: 1, + transactionIndex: 0, + transactionHash: '0xabcdef', + logIndex: 0, + address: '0x1234567890', + }, + { + topics: ['0xabcdef'], + data: '0x', + blockNumber: 2, + transactionIndex: 1, + transactionHash: '0xabcdef', + logIndex: 1, + address: '0xabcdef', + }, + ], + }; + + const iface: Interface = new Interface([]); + + test('should return the correct log when the event is found', () => { + const eventName = 'EventName'; + const expectedLog: LogDescription = { + topics: ['0x1234567890'], + data: '0x', + blockNumber: 1, + transactionIndex: 0, + transactionHash: '0xabcdef', + logIndex: 0, + address: '0x1234567890', + }; + + const result = findEventTopicLog(cr, iface, eventName); + + expect(result).toEqual(expectedLog); + }); + + test('should throw an error when the event is not found', () => { + const eventName = 'NonExistentEvent'; + + expect(() => { + findEventTopicLog(cr, iface, eventName); + }).toThrowError('EventNotFoundError'); + }); +}); \ No newline at end of file diff --git a/sdk/src/events/utils.ts b/sdk/src/events/utils.ts new file mode 100644 index 00000000..aaf2f98a --- /dev/null +++ b/sdk/src/events/utils.ts @@ -0,0 +1,43 @@ +import {EventNotFoundError} from './errors'; +import {ContractReceipt} from '@ethersproject/contracts'; +import {Interface, LogDescription} from 'ethers/lib/utils'; + +/** + * Finds a typed event in transaction given the event name + * + * @export + * @param {ContractReceipt} cr + * @param {string} eventName + * @return {*} {(T)} + */ +export function findEvent(cr: ContractReceipt, eventName: string): T { + const event = (cr.events || []).find(event => event.event === eventName); + + if (!event) { + throw new EventNotFoundError(eventName, cr); + } + + return event as T; +} + +/** + * Finds a log in a transaction given the interface of the emitting contract and the event name + * + * @export + * @param {ContractReceipt} cr + * @param {Interface} iface + * @param {string} eventName + * @return {*} {LogDescription & (T | LogDescription)} + */ +export function findEventTopicLog( + cr: ContractReceipt, + iface: Interface, + eventName: string +): LogDescription & (T | LogDescription) { + const topic = iface.getEventTopic(eventName); + const log = cr.logs.find(x => x.topics[0] === topic); + if (!log) { + throw new EventNotFoundError(eventName, cr); + } + return iface.parseLog(log) as LogDescription & (T | LogDescription); +} diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 674358e2..9a772e26 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -1,9 +1,5 @@ -export * from './context-core'; -export * from './client-core'; -export * from './context'; export * from './constants'; export * from './types'; -export * from './utils'; export * from './schemas'; export * from './validation'; export * from './multiuri'; diff --git a/sdk/src/utils.ts b/sdk/src/utils.ts index 6c66fd92..2434f633 100644 --- a/sdk/src/utils.ts +++ b/sdk/src/utils.ts @@ -160,9 +160,9 @@ export async function* prepareGenericInstallation( key: PrepareInstallationStep.PREPARING, txHash: tx.hash, }; - - const event = await findEventTopicLog( - tx, + const cr = await tx.wait(); + const event = findEventTopicLog( + cr, PluginSetupProcessor__factory.createInterface(), 'InstallationPrepared' ); @@ -290,9 +290,9 @@ export async function* prepareGenericUpdate( key: PrepareUpdateStep.PREPARING, txHash: tx.hash, }; - - const event = await findEventTopicLog( - tx, + const cr = await tx.wait(); + const event = findEventTopicLog( + cr, PluginSetupProcessor__factory.createInterface(), 'UpdatePrepared' ); diff --git a/sdk/test/constants.ts b/sdk/test/constants.ts index 015bca95..8e206a34 100644 --- a/sdk/test/constants.ts +++ b/sdk/test/constants.ts @@ -151,3 +151,4 @@ export const ERC165_ABI = [ type: 'function', }, ]; + diff --git a/sdk/test/unit/bitmap.test.ts b/sdk/test/unit/bitmap.test.ts new file mode 100644 index 00000000..d5a54fb2 --- /dev/null +++ b/sdk/test/unit/bitmap.test.ts @@ -0,0 +1,116 @@ +import { + bitmapToBoolArray, + flipBit, + getBit, + boolArrayToBitmap, +} from '../../src/bitmap'; +import {getEmpty256Array} from '../utils'; +import {BigNumber} from '@ethersproject/bignumber'; + +describe('bitmap', () => { + describe('flipBit', () => { + test('should flip the bit at the given index', function () { + const inputs = [ + {index: 0, num: BigNumber.from(0), expected: BigNumber.from(1)}, + {index: 2, num: BigNumber.from(0), expected: BigNumber.from(4)}, + {index: 2, num: BigNumber.from(10), expected: BigNumber.from(14)}, + ]; + for (const input of inputs) { + const flippedNum = flipBit(input.index, input.num); + expect(flippedNum.toString()).toEqual(input.expected.toString()); + } + }); + }); + describe('getBit', () => { + test('should return true if the bit at the given index is set', function () { + const inputs = [ + {index: 0, num: BigNumber.from(1), expected: true}, + {index: 2, num: BigNumber.from(4), expected: true}, + {index: 2, num: BigNumber.from(14), expected: true}, + ]; + for (const input of inputs) { + const isSet = getBit(input.index, input.num); + expect(isSet).toEqual(input.expected); + } + }); + test('should return false if the bit at the given index is not set', function () { + const inputs = [ + {index: 0, num: BigNumber.from(0), expected: false}, + {index: 2, num: BigNumber.from(0), expected: false}, + {index: 2, num: BigNumber.from(10), expected: false}, + ]; + for (const input of inputs) { + const isSet = getBit(input.index, input.num); + expect(isSet).toEqual(input.expected); + } + }); + }); + + describe('bitmapToBoolArray', () => { + it('should fail when the bigint is too large', () => { + expect(() => { + bitmapToBoolArray(BigInt(1) << BigInt(256)); + }).toThrow(); + }); + it('should transform a bigint bitmap into a boolean array', () => { + const tests = [{input: BigInt(0), output: getEmpty256Array()}]; + let output = getEmpty256Array(); + output[0] = true; + tests.push({input: BigInt(1) << BigInt(0), output}); + + output = getEmpty256Array(); + output[1] = true; + tests.push({input: BigInt(1) << BigInt(1), output}); + + output = getEmpty256Array(); + output[2] = true; + tests.push({input: BigInt(1) << BigInt(2), output}); + + output = getEmpty256Array(); + output[5] = true; + tests.push({input: BigInt(1) << BigInt(5), output}); + + output = getEmpty256Array(); + output[100] = true; + tests.push({input: BigInt(1) << BigInt(100), output}); + + output = getEmpty256Array(); + output[150] = true; + tests.push({input: BigInt(1) << BigInt(150), output}); + + for (const entry of tests) { + expect(bitmapToBoolArray(entry.input)).toMatchObject(entry.output); + } + }); + }); + describe('boolArrayToBitMap', () => { + it('boolArrayToBitmap should fail when the array is too large', () => { + expect(() => { + const tmp = getEmpty256Array(); + tmp.push(false); + boolArrayToBitmap(tmp); + }).toThrow(); + }); + it('should transform a boolean array into a bigint bitmap', () => { + const tests = [ + {input: getEmpty256Array(), output: BigInt(0)}, + {input: getEmpty256Array().fill(true), output: BigInt(2 ** 256) - BigInt(1)}, + ]; + let input = getEmpty256Array(); + input[0] = true; + tests.push({input, output: BigInt(1) << BigInt(0)}); + + input = getEmpty256Array(); + input[100] = true; + tests.push({input, output: BigInt(1) << BigInt(100)}); + + input = getEmpty256Array(); + input[150] = true; + tests.push({input, output: BigInt(1) << BigInt(150)}); + + for (const entry of tests) { + expect(boolArrayToBitmap(entry.input)).toEqual(entry.output); + } + }); + }); +}); diff --git a/sdk/test/unit/encoding.test.ts b/sdk/test/unit/encoding.test.ts index 8c737ba5..8ec7dbd1 100644 --- a/sdk/test/unit/encoding.test.ts +++ b/sdk/test/unit/encoding.test.ts @@ -1,7 +1,5 @@ import {InvalidProposalIdError} from '../../src'; import { - bitmapToBoolArray, - boolArrayToBitmap, bytesToHex, decodeProposalId, decodeRatio, @@ -273,80 +271,6 @@ describe('Test encoding helper functions', () => { } }); }); - describe('boolArrayToBitmap', () => { - it('boolArrayToBitmap should fail when the array is too large', () => { - expect(() => { - const tmp = getEmpty256Array(); - tmp.push(false); - boolArrayToBitmap(tmp); - }).toThrow(); - }); - it('should transform a boolean array into a bigint bitmap', () => { - const tests = [ - {input: undefined, output: BigInt(0)}, - {input: [], output: BigInt(0)}, - {input: [false], output: BigInt(0)}, - {input: [true], output: BigInt(1)}, - {input: [true, false], output: BigInt(1)}, - {input: [true, false, false, false, false, false], output: BigInt(1)}, - {input: [false, true, false, true], output: BigInt(10)}, - {input: getEmpty256Array(), output: BigInt(0)}, - ]; - let input = getEmpty256Array(); - input[0] = true; - tests.push({input, output: BigInt(1) << BigInt(0)}); - - input = getEmpty256Array(); - input[100] = true; - tests.push({input, output: BigInt(1) << BigInt(100)}); - - input = getEmpty256Array(); - input[150] = true; - tests.push({input, output: BigInt(1) << BigInt(150)}); - - for (const entry of tests) { - expect(boolArrayToBitmap(entry.input)).toEqual(entry.output); - } - }); - }); - describe('bitmapToBoolArray', () => { - it('should transform a bigint bitmap into a boolean array', () => { - const tests = [{input: BigInt(0), output: getEmpty256Array()}]; - let output = getEmpty256Array(); - output[0] = true; - tests.push({input: BigInt(1) << BigInt(0), output}); - - output = getEmpty256Array(); - output[1] = true; - tests.push({input: BigInt(1) << BigInt(1), output}); - - output = getEmpty256Array(); - output[2] = true; - tests.push({input: BigInt(1) << BigInt(2), output}); - - output = getEmpty256Array(); - output[5] = true; - tests.push({input: BigInt(1) << BigInt(5), output}); - - output = getEmpty256Array(); - output[100] = true; - tests.push({input: BigInt(1) << BigInt(100), output}); - - output = getEmpty256Array(); - output[150] = true; - tests.push({input: BigInt(1) << BigInt(150), output}); - - for (const entry of tests) { - expect(bitmapToBoolArray(entry.input)).toMatchObject(entry.output); - } - }); - - it('should fail when the bigint is too large', () => { - expect(() => { - bitmapToBoolArray(BigInt(1) << BigInt(256)); - }).toThrow(); - }); - }); describe('getExtendedProposalId', () => { it('Should get an extended version of a proposal id', () => { const entries = [ diff --git a/sdk/test/unit/events.test.ts b/sdk/test/unit/events.test.ts new file mode 100644 index 00000000..49a77798 --- /dev/null +++ b/sdk/test/unit/events.test.ts @@ -0,0 +1,52 @@ +import {DaoEvents, IDaoEvents, findEvent, findEventTopicLog} from '../../src'; +import {getContractReceipt} from '../utils'; +import {DAO__factory} from '@aragon/osx-ethers'; +import {EventFragment, Interface} from '@ethersproject/abi'; +import {Event} from '@ethersproject/contracts'; +import {ContractReceipt} from '@ethersproject/contracts'; + +describe('events', () => { + let event: EventFragment; + let iface: Interface; + const eventName = DaoEvents.NEW_URI; + const eventArgs = ['https://aragon.org']; + let cr: ContractReceipt; + beforeAll(() => { + iface = DAO__factory.createInterface(); + event = iface.getEvent(eventName); + cr = getContractReceipt(event, eventArgs); + }); + describe('findEvent', () => { + it('should not find the event in the contract receipt and throw an error', () => { + expect(() => { + findEvent(cr, IDaoEvents.DEPOSITED); + }).toThrow(); + }); + it('should find the event in the contract receipt', () => { + const cr = getContractReceipt(event, eventArgs); + const e = findEvent(cr, eventName); + expect(e).toBeDefined(); + expect(e.event).toEqual(eventName); + expect(e.args).toBeDefined(); + for (const [i, arg] of e.args!.entries()) { + expect(arg).toBe(eventArgs[i]); + } + }); + }); + describe('findEventTopicLog', () => { + it('should not find the event in the contract receipt and throw an error', () => { + expect(() => { + findEventTopicLog(cr, iface, IDaoEvents.DEPOSITED); + }).toThrow(); + }); + it('should find the event topic in the contract receipt', () => { + const log = findEventTopicLog(cr, iface, eventName); + expect(log).toBeDefined(); + expect(log.name).toEqual(eventName); + expect(log.args).toBeDefined(); + for (const [i, arg] of log.args!.entries()) { + expect(arg).toBe(eventArgs[i]); + } + }); + }); +}); diff --git a/sdk/test/utils.ts b/sdk/test/utils.ts index 71e67709..0edb170a 100644 --- a/sdk/test/utils.ts +++ b/sdk/test/utils.ts @@ -1,3 +1,172 @@ +import {Interface, defaultAbiCoder, EventFragment} from '@ethersproject/abi'; +import {Log} from '@ethersproject/abstract-provider'; +import {BigNumber} from '@ethersproject/bignumber'; +import {ContractReceipt, Event} from '@ethersproject/contracts'; +import {id} from '@ethersproject/hash'; + export function getEmpty256Array() { return new Array(256).fill(false); } + +export function getDummyLog(event: EventFragment, eventArgs: any[]): Log { + const inputs = event.inputs.map(i => i.type); + + return { + address: '', + blockNumber: 0, + transactionIndex: 0, + transactionHash: '', + blockHash: '', + removed: false, + logIndex: 0, + data: defaultAbiCoder.encode(inputs, eventArgs), + topics: [id(event.format())], + }; +} + +export function getDummyEvent(event: EventFragment, log: Log): Event { + const e = {} as Event; + return { + ...log, + ...e, + event: event.name, + args: defaultAbiCoder.decode(event.inputs, log.data), + }; +} +// { +// to: "0xF3c6CF1C13EcC07204BEFce90EE14B5Bf8BbA4c9", +// from: "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199", +// contractAddress: null, +// transactionIndex: 0, +// gasUsed: { +// _hex: "0x049339", +// _isBigNumber: true, +// }, +// logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000080000000000000008000000000002000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000100000000000000000000000000000000800000000000000000000000000020000000000000000000000000000000000000000000000100000000000000000000", +// blockHash: "0x2c912bbbeae5fa740f1df1f8f1245bffe1e8b0968f3a6e88b415f344eac0a64f", +// transactionHash: "0xb4592c2f9246ebca1b35cb3e6187dbc5bf49935e5cd7bf11a5ba96e998b412a6", +// logs: [ +// { +// transactionIndex: 0, +// blockNumber: 39, +// transactionHash: "0xb4592c2f9246ebca1b35cb3e6187dbc5bf49935e5cd7bf11a5ba96e998b412a6", +// address: "0xF3c6CF1C13EcC07204BEFce90EE14B5Bf8BbA4c9", +// topics: [ +// "0xa6c1f8f4276dc3f243459e13b557c84e8f4e90b2e09070bad5f6909cee687c92", +// "0x0000000000000000000000000000000000000000000000000000000000000000", +// "0x0000000000000000000000008626f6940e2eb28930efb4cef49b2d1f2c9c1199", +// ], +// data: "0x0000000000000000000000000000000000000000000000000000000065d403d50000000000000000000000000000000000000000000000000000000065d411e500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d58684a6177544a33506b6f4b4d79463361344438397a796241486a70634769766b623746314e6b48416a706f000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f3c6cf1c13ecc07204befce90ee14b5bf8bba4c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a40dfb278e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000007a1200000000000000000000000000000000000000000000000000000000000001c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", +// logIndex: 0, +// blockHash: "0x2c912bbbeae5fa740f1df1f8f1245bffe1e8b0968f3a6e88b415f344eac0a64f", +// }, +// ], +// blockNumber: 39, +// confirmations: 1, +// cumulativeGasUsed: { +// _hex: "0x049339", +// _isBigNumber: true, +// }, +// effectiveGasPrice: { +// _hex: "0x59f2bdfb", +// _isBigNumber: true, +// }, +// status: 1, +// type: 2, +// byzantium: true, +// events: [ +// { +// transactionIndex: 0, +// blockNumber: 39, +// transactionHash: "0xb4592c2f9246ebca1b35cb3e6187dbc5bf49935e5cd7bf11a5ba96e998b412a6", +// address: "0xF3c6CF1C13EcC07204BEFce90EE14B5Bf8BbA4c9", +// topics: [ +// "0xa6c1f8f4276dc3f243459e13b557c84e8f4e90b2e09070bad5f6909cee687c92", +// "0x0000000000000000000000000000000000000000000000000000000000000000", +// "0x0000000000000000000000008626f6940e2eb28930efb4cef49b2d1f2c9c1199", +// ], +// data: "0x0000000000000000000000000000000000000000000000000000000065d403d50000000000000000000000000000000000000000000000000000000065d411e500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d58684a6177544a33506b6f4b4d79463361344438397a796241486a70634769766b623746314e6b48416a706f000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f3c6cf1c13ecc07204befce90ee14b5bf8bba4c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a40dfb278e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000007a1200000000000000000000000000000000000000000000000000000000000001c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", +// logIndex: 0, +// blockHash: "0x2c912bbbeae5fa740f1df1f8f1245bffe1e8b0968f3a6e88b415f344eac0a64f", +// args: [ +// { +// _hex: "0x00", +// _isBigNumber: true, +// }, +// "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199", +// { +// _hex: "0x65d403d5", +// _isBigNumber: true, +// }, +// { +// _hex: "0x65d411e5", +// _isBigNumber: true, +// }, +// "0x697066733a2f2f516d58684a6177544a33506b6f4b4d79463361344438397a796241486a70634769766b623746314e6b48416a706f", +// [ +// [ +// "0xF3c6CF1C13EcC07204BEFce90EE14B5Bf8BbA4c9", +// { +// _hex: "0x00", +// _isBigNumber: true, +// }, +// "0x0dfb278e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000007a1200000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000000000", +// ], +// ], +// { +// _hex: "0x00", +// _isBigNumber: true, +// }, +// ], +// decode: function (data, topics) { +// return contract.interface.decodeEventLog(parsed.eventFragment, data, topics); +// }, +// event: "ProposalCreated", +// eventSignature: "ProposalCreated(uint256,address,uint64,uint64,bytes,(address,uint256,bytes)[],uint256)", +// removeListener: function () { return contract.provider; }, +// getBlock: function () { +// return contract.provider.getBlock(receipt.blockHash); +// }, +// getTransaction: function () { +// return contract.provider.getTransaction(receipt.transactionHash); +// }, +// getTransactionReceipt: function () { +// return Promise.resolve(receipt); +// }, +// }, +// ], +// } + +export function getInterface(event: string): Interface { + return new Interface(event); +} +export function getContractReceipt( + event: EventFragment, + eventArgs: any[] +): ContractReceipt { + const logs = [getDummyLog(event, eventArgs)]; + const events = [getDummyEvent(event, logs[0])]; + return { + to: '', + from: '', + contractAddress: '', + transactionHash: '', + transactionIndex: 0, + blockHash: '', + blockNumber: 0, + cumulativeGasUsed: BigNumber.from(0), + gasUsed: BigNumber.from(0), + effectiveGasPrice: BigNumber.from(0), + logsBloom: '', + confirmations: 0, + byzantium: true, + type: 0, + status: 1, + logs, + events, + }; +} + +export function findEventInAbi(iface: Interface, eventName: string) { + return iface.getEventTopic(eventName); +}