From 871f039ff79b486b12888406371ace4df4c7dba3 Mon Sep 17 00:00:00 2001 From: josemarinas <36479864+josemarinas@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:25:45 +0200 Subject: [PATCH] chore: remove SDK 1.0 related code from osx-sdk (#72) * remove: SDK 1.0 unused folders, functions and constants * update: changelog --- sdk/CHANGELOG.md | 4 + sdk/src/client-core.ts | 24 - sdk/src/constants.ts | 433 ------------ sdk/src/context-core.ts | 436 ------------ sdk/src/context.ts | 9 - sdk/src/index.ts | 5 - sdk/src/internal/constants.ts | 1 - sdk/src/internal/graphql-queries/index.ts | 2 - sdk/src/internal/graphql-queries/plugin.ts | 23 - sdk/src/internal/graphql-queries/status.ts | 9 - sdk/src/internal/index.ts | 3 - sdk/src/internal/interfaces.ts | 53 -- sdk/src/internal/modules/graphql.ts | 110 --- sdk/src/internal/modules/index.ts | 3 - sdk/src/internal/modules/ipfs.ts | 111 --- sdk/src/internal/modules/web3.ts | 151 ---- sdk/src/internal/types.ts | 90 --- sdk/src/schemas.ts | 106 --- sdk/src/types.ts | 245 ------- sdk/src/utils.ts | 355 ---------- sdk/test/schemas.test.ts | 781 --------------------- sdk/test/unit/client.test.ts | 115 --- sdk/test/unit/context.test.ts | 295 -------- 23 files changed, 4 insertions(+), 3360 deletions(-) delete mode 100644 sdk/src/client-core.ts delete mode 100644 sdk/src/context-core.ts delete mode 100644 sdk/src/context.ts delete mode 100644 sdk/src/internal/constants.ts delete mode 100644 sdk/src/internal/graphql-queries/index.ts delete mode 100644 sdk/src/internal/graphql-queries/plugin.ts delete mode 100644 sdk/src/internal/graphql-queries/status.ts delete mode 100644 sdk/src/internal/index.ts delete mode 100644 sdk/src/internal/interfaces.ts delete mode 100644 sdk/src/internal/modules/graphql.ts delete mode 100644 sdk/src/internal/modules/index.ts delete mode 100644 sdk/src/internal/modules/ipfs.ts delete mode 100644 sdk/src/internal/modules/web3.ts delete mode 100644 sdk/src/internal/types.ts delete mode 100644 sdk/src/schemas.ts delete mode 100644 sdk/src/utils.ts delete mode 100644 sdk/test/schemas.test.ts delete mode 100644 sdk/test/unit/client.test.ts delete mode 100644 sdk/test/unit/context.test.ts diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index c8359726..cc972eee 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `resolveEnsName` functions +### Removed + +- SDK 1.0 related code that is not going to be used. + ## v0.0.1 ### Changed diff --git a/sdk/src/client-core.ts b/sdk/src/client-core.ts deleted file mode 100644 index 85240b17..00000000 --- a/sdk/src/client-core.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {Context} from './context'; -import { - GraphqlModule, - IClientCore, - IClientGraphQLCore, - IClientIpfsCore, - IClientWeb3Core, - IPFSModule, - Web3Module, -} from './internal'; - -/** - * Provides the low level foundation so that subclasses have ready-made access to Web3, IPFS and GraphQL primitives - */ -export abstract class ClientCore implements IClientCore { - public web3: IClientWeb3Core; - public ipfs: IClientIpfsCore; - public graphql: IClientGraphQLCore; - constructor(context: Context) { - this.web3 = new Web3Module(context); - this.ipfs = new IPFSModule(context); - this.graphql = new GraphqlModule(context); - } -} diff --git a/sdk/src/constants.ts b/sdk/src/constants.ts index fc04394d..a25a3e0a 100644 --- a/sdk/src/constants.ts +++ b/sdk/src/constants.ts @@ -1,43 +1,3 @@ -import {NetworkDeployment} from './internal'; -import {TIME} from './time'; -import {ProposalMetadata, SupportedNetwork, SupportedVersion} from './types'; -import {activeContractsList} from '@aragon/osx-ethers'; -import {activeContractsList as activeContractsListV1_0_0} from '@aragon/osx-ethers-v1.0.0'; -import {keccak256} from '@ethersproject/keccak256'; -import {Network} from '@ethersproject/networks'; -import {toUtf8Bytes} from '@ethersproject/strings'; - -/** Timeout that will be applied to operations involving - * many fetch requests that could take a long time */ -export const MULTI_FETCH_TIMEOUT = 7 * TIME.SECOND_MS; - -type GraphqlNetworks = - | 'mainnet' - | 'goerli' - | 'sepolia' - | 'polygon' - | 'mumbai' - | 'baseMainnet' - | 'baseGoerli' - | 'arbitrum' - | 'arbitrumGoerli' - | 'local'; - -const SupportedNetworksToGraphqlNetworks: { - [K in SupportedNetwork]: GraphqlNetworks; -} = { - [SupportedNetwork.MAINNET]: 'mainnet', - [SupportedNetwork.GOERLI]: 'goerli', - [SupportedNetwork.SEPOLIA]: 'sepolia', - [SupportedNetwork.POLYGON]: 'polygon', - [SupportedNetwork.MUMBAI]: 'mumbai', - [SupportedNetwork.BASE]: 'baseMainnet', - [SupportedNetwork.BASE_GOERLI]: 'baseGoerli', - [SupportedNetwork.ARBITRUM]: 'arbitrum', - [SupportedNetwork.ARBITRUM_GOERLI]: 'arbitrumGoerli', - [SupportedNetwork.LOCAL]: 'local', -}; - export const ADDRESS = { ZERO: `0x${'0'.repeat(40)}`, // address(0) ONE: `0x${'0'.repeat(39)}1`, // address(1) @@ -45,399 +5,6 @@ export const ADDRESS = { LAST: `0x${'f'.repeat(40)}`, // address(-1) }; -export const UNSUPPORTED_PROPOSAL_METADATA_LINK: ProposalMetadata = { - title: '(unsupported metadata link)', - summary: '(the link to the metadata is not supported)', - description: '(the link to the metadata is not supported)', - resources: [], -}; -export const EMPTY_PROPOSAL_METADATA_LINK: ProposalMetadata = { - title: '(the proposal has no metadata)', - summary: '(the current proposal does not have any content defined)', - description: '(the current proposal does not have any content defined)', - resources: [], -}; -export const UNAVAILABLE_PROPOSAL_METADATA: ProposalMetadata = { - title: '(unavailable metadata)', - summary: '(the proposal metadata is not available)', - description: '(the proposal metadata is not available)', - resources: [], -}; - -const getGraphqlNode = (network: SupportedNetwork): string => { - return `https://subgraph.satsuma-prod.com/qHR2wGfc5RLi6/aragon/osx-${SupportedNetworksToGraphqlNetworks[network]}/version/v1.3.0/api`; -}; - -export const GRAPHQL_NODES: {[K in SupportedNetwork]: {url: string}[]} = { - [SupportedNetwork.MAINNET]: [ - { - url: getGraphqlNode(SupportedNetwork.MAINNET), - }, - ], - [SupportedNetwork.GOERLI]: [{url: getGraphqlNode(SupportedNetwork.GOERLI)}], - [SupportedNetwork.SEPOLIA]: [ - { - url: getGraphqlNode(SupportedNetwork.SEPOLIA), - }, - ], - [SupportedNetwork.POLYGON]: [ - { - url: getGraphqlNode(SupportedNetwork.POLYGON), - }, - ], - [SupportedNetwork.MUMBAI]: [{url: getGraphqlNode(SupportedNetwork.MUMBAI)}], - [SupportedNetwork.BASE]: [{url: getGraphqlNode(SupportedNetwork.BASE)}], - [SupportedNetwork.BASE_GOERLI]: [ - { - url: getGraphqlNode(SupportedNetwork.BASE_GOERLI), - }, - ], - [SupportedNetwork.ARBITRUM]: [ - {url: getGraphqlNode(SupportedNetwork.ARBITRUM)}, - ], - [SupportedNetwork.ARBITRUM_GOERLI]: [ - { - url: getGraphqlNode(SupportedNetwork.ARBITRUM_GOERLI), - }, - ], - [SupportedNetwork.LOCAL]: [{url: getGraphqlNode(SupportedNetwork.LOCAL)}], -}; - -const IPFS_ENDPOINTS = { - prod: [ - { - url: 'https://prod.ipfs.aragon.network/api/v0', - headers: { - 'X-API-KEY': 'b477RhECf8s8sdM7XrkLBs2wHc4kCMwpbcFC55Kt', - }, - }, - ], - test: [ - { - url: 'https://test.ipfs.aragon.network/api/v0', - headers: { - 'X-API-KEY': 'b477RhECf8s8sdM7XrkLBs2wHc4kCMwpbcFC55Kt', - }, - }, - ], -}; - -export const IPFS_NODES: { - [K in SupportedNetwork]: { - url: string; - headers?: Record | undefined; - }[]; -} = { - [SupportedNetwork.MAINNET]: IPFS_ENDPOINTS.prod, - [SupportedNetwork.GOERLI]: IPFS_ENDPOINTS.test, - [SupportedNetwork.SEPOLIA]: IPFS_ENDPOINTS.test, - [SupportedNetwork.POLYGON]: IPFS_ENDPOINTS.prod, - [SupportedNetwork.MUMBAI]: IPFS_ENDPOINTS.test, - [SupportedNetwork.BASE]: IPFS_ENDPOINTS.prod, - [SupportedNetwork.BASE_GOERLI]: IPFS_ENDPOINTS.test, - [SupportedNetwork.ARBITRUM]: IPFS_ENDPOINTS.prod, - [SupportedNetwork.ARBITRUM_GOERLI]: IPFS_ENDPOINTS.test, - [SupportedNetwork.LOCAL]: IPFS_ENDPOINTS.test, -}; - -const NOT_DEPLOYED = { - daoFactoryAddress: '', - pluginSetupProcessorAddress: '', - multisigRepoAddress: '', - adminRepoAddress: '', - addresslistVotingRepoAddress: '', - tokenVotingRepoAddress: '', - multisigSetupAddress: '', - adminSetupAddress: '', - addresslistVotingSetupAddress: '', - tokenVotingSetupAddress: '', - ensRegistryAddress: '', -}; - -export const LIVE_CONTRACTS: { - [J in SupportedVersion]: {[K in SupportedNetwork]: NetworkDeployment}; -} = { - [SupportedVersion.V1_0_0]: { - [SupportedNetwork.MAINNET]: { - daoFactoryAddress: activeContractsListV1_0_0.mainnet.DAOFactory, - pluginSetupProcessorAddress: - activeContractsListV1_0_0.mainnet.PluginRepoFactory, - multisigRepoAddress: activeContractsListV1_0_0.mainnet['multisig-repo'], - adminRepoAddress: activeContractsListV1_0_0.mainnet['admin-repo'], - addresslistVotingRepoAddress: - activeContractsListV1_0_0.mainnet['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsListV1_0_0.mainnet['token-voting-repo'], - multisigSetupAddress: activeContractsListV1_0_0.mainnet.MultisigSetup, - adminSetupAddress: activeContractsListV1_0_0.mainnet.AdminSetup, - addresslistVotingSetupAddress: - activeContractsListV1_0_0.mainnet.AddresslistVotingSetup, - tokenVotingSetupAddress: - activeContractsListV1_0_0.mainnet.TokenVotingSetup, - }, - [SupportedNetwork.GOERLI]: { - daoFactoryAddress: activeContractsListV1_0_0.goerli.DAOFactory, - pluginSetupProcessorAddress: - activeContractsListV1_0_0.goerli.PluginSetupProcessor, - multisigRepoAddress: activeContractsListV1_0_0.goerli['multisig-repo'], - adminRepoAddress: activeContractsListV1_0_0.goerli['admin-repo'], - addresslistVotingRepoAddress: - activeContractsListV1_0_0.goerli['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsListV1_0_0.goerli['token-voting-repo'], - multisigSetupAddress: activeContractsListV1_0_0.goerli.MultisigSetup, - adminSetupAddress: activeContractsListV1_0_0.goerli.AdminSetup, - addresslistVotingSetupAddress: - activeContractsListV1_0_0.goerli.AddresslistVotingSetup, - tokenVotingSetupAddress: - activeContractsListV1_0_0.goerli.TokenVotingSetup, - }, - [SupportedNetwork.SEPOLIA]: NOT_DEPLOYED, - [SupportedNetwork.POLYGON]: { - daoFactoryAddress: activeContractsListV1_0_0.polygon.DAOFactory, - pluginSetupProcessorAddress: - activeContractsListV1_0_0.polygon.PluginSetupProcessor, - multisigRepoAddress: activeContractsListV1_0_0.polygon['multisig-repo'], - adminRepoAddress: activeContractsListV1_0_0.polygon['admin-repo'], - addresslistVotingRepoAddress: - activeContractsListV1_0_0.polygon['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsListV1_0_0.polygon['token-voting-repo'], - multisigSetupAddress: activeContractsListV1_0_0.polygon.MultisigSetup, - adminSetupAddress: activeContractsListV1_0_0.polygon.AdminSetup, - addresslistVotingSetupAddress: - activeContractsListV1_0_0.polygon.AddresslistVotingSetup, - tokenVotingSetupAddress: - activeContractsListV1_0_0.polygon.TokenVotingSetup, - ensRegistryAddress: activeContractsListV1_0_0.polygon.ENSRegistry, - }, - [SupportedNetwork.MUMBAI]: { - daoFactoryAddress: activeContractsListV1_0_0.mumbai.DAOFactory, - pluginSetupProcessorAddress: - activeContractsListV1_0_0.mumbai.PluginSetupProcessor, - multisigRepoAddress: activeContractsListV1_0_0.mumbai['multisig-repo'], - adminRepoAddress: activeContractsListV1_0_0.mumbai['admin-repo'], - addresslistVotingRepoAddress: - activeContractsListV1_0_0.mumbai['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsListV1_0_0.mumbai['token-voting-repo'], - multisigSetupAddress: activeContractsListV1_0_0.mumbai.MultisigSetup, - adminSetupAddress: activeContractsListV1_0_0.mumbai.AdminSetup, - addresslistVotingSetupAddress: - activeContractsListV1_0_0.mumbai.AddresslistVotingSetup, - tokenVotingSetupAddress: - activeContractsListV1_0_0.mumbai.TokenVotingSetup, - ensRegistryAddress: activeContractsListV1_0_0.mumbai.ENSRegistry, - }, - [SupportedNetwork.BASE]: NOT_DEPLOYED, - [SupportedNetwork.BASE_GOERLI]: NOT_DEPLOYED, - [SupportedNetwork.ARBITRUM]: NOT_DEPLOYED, - [SupportedNetwork.ARBITRUM_GOERLI]: NOT_DEPLOYED, - [SupportedNetwork.LOCAL]: NOT_DEPLOYED, - }, - [SupportedVersion.V1_3_0]: { - [SupportedNetwork.MAINNET]: { - daoFactoryAddress: activeContractsList.mainnet.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.mainnet.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.mainnet['multisig-repo'], - adminRepoAddress: activeContractsList.mainnet['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.mainnet['address-list-voting-repo'], - tokenVotingRepoAddress: activeContractsList.mainnet['token-voting-repo'], - multisigSetupAddress: activeContractsList.mainnet.MultisigSetup, - adminSetupAddress: activeContractsList.mainnet.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.mainnet.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.mainnet.TokenVotingSetup, - }, - [SupportedNetwork.GOERLI]: { - daoFactoryAddress: activeContractsList.goerli.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.goerli.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.goerli['multisig-repo'], - adminRepoAddress: activeContractsList.goerli['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.goerli['address-list-voting-repo'], - tokenVotingRepoAddress: activeContractsList.goerli['token-voting-repo'], - multisigSetupAddress: activeContractsList.goerli.MultisigSetup, - adminSetupAddress: activeContractsList.goerli.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.goerli.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.goerli.TokenVotingSetup, - }, - [SupportedNetwork.SEPOLIA]: { - daoFactoryAddress: activeContractsList.sepolia.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.sepolia.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.sepolia['multisig-repo'], - adminRepoAddress: activeContractsList.sepolia['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.sepolia['address-list-voting-repo'], - tokenVotingRepoAddress: activeContractsList.sepolia['token-voting-repo'], - multisigSetupAddress: activeContractsList.sepolia.MultisigSetup, - adminSetupAddress: activeContractsList.sepolia.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.sepolia.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.sepolia.TokenVotingSetup, - ensRegistryAddress: activeContractsList.sepolia.ENSRegistry, - }, - [SupportedNetwork.POLYGON]: { - daoFactoryAddress: activeContractsList.polygon.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.polygon.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.polygon['multisig-repo'], - adminRepoAddress: activeContractsList.polygon['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.polygon['address-list-voting-repo'], - tokenVotingRepoAddress: activeContractsList.polygon['token-voting-repo'], - multisigSetupAddress: activeContractsList.polygon.MultisigSetup, - adminSetupAddress: activeContractsList.polygon.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.polygon.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.polygon.TokenVotingSetup, - ensRegistryAddress: activeContractsList.polygon.ENSRegistry, - }, - [SupportedNetwork.MUMBAI]: { - daoFactoryAddress: activeContractsList.mumbai.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.mumbai.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.mumbai['multisig-repo'], - adminRepoAddress: activeContractsList.mumbai['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.mumbai['address-list-voting-repo'], - tokenVotingRepoAddress: activeContractsList.mumbai['token-voting-repo'], - multisigSetupAddress: activeContractsList.mumbai.MultisigSetup, - adminSetupAddress: activeContractsList.mumbai.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.mumbai.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.mumbai.TokenVotingSetup, - ensRegistryAddress: activeContractsList.mumbai.ENSRegistry, - }, - [SupportedNetwork.BASE]: { - daoFactoryAddress: activeContractsList.baseMainnet.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.baseMainnet.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.baseMainnet['multisig-repo'], - adminRepoAddress: activeContractsList.baseMainnet['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.baseMainnet['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsList.baseMainnet['token-voting-repo'], - multisigSetupAddress: activeContractsList.baseMainnet.MultisigSetup, - adminSetupAddress: activeContractsList.baseMainnet.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.baseMainnet.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.baseMainnet.TokenVotingSetup, - ensRegistryAddress: activeContractsList.baseMainnet.ENSRegistry, - }, - [SupportedNetwork.BASE_GOERLI]: { - daoFactoryAddress: activeContractsList.baseGoerli.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.baseGoerli.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.baseGoerli['multisig-repo'], - adminRepoAddress: activeContractsList.baseGoerli['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.baseGoerli['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsList.baseGoerli['token-voting-repo'], - multisigSetupAddress: activeContractsList.baseGoerli.MultisigSetup, - adminSetupAddress: activeContractsList.baseGoerli.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.baseGoerli.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.baseGoerli.TokenVotingSetup, - ensRegistryAddress: activeContractsList.baseGoerli.ENSRegistry, - }, - [SupportedNetwork.ARBITRUM]: { - daoFactoryAddress: activeContractsList.arbitrum.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.arbitrum.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.arbitrum['multisig-repo'], - adminRepoAddress: activeContractsList.arbitrum['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.arbitrum['address-list-voting-repo'], - tokenVotingRepoAddress: activeContractsList.arbitrum['token-voting-repo'], - multisigSetupAddress: activeContractsList.arbitrum.MultisigSetup, - adminSetupAddress: activeContractsList.arbitrum.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.arbitrum.AddresslistVotingSetup, - tokenVotingSetupAddress: activeContractsList.arbitrum.TokenVotingSetup, - ensRegistryAddress: activeContractsList.arbitrum.ENSRegistry, - }, - [SupportedNetwork.ARBITRUM_GOERLI]: { - daoFactoryAddress: activeContractsList.arbitrumGoerli.DAOFactory, - pluginSetupProcessorAddress: - activeContractsList.arbitrumGoerli.PluginSetupProcessor, - multisigRepoAddress: activeContractsList.arbitrumGoerli['multisig-repo'], - adminRepoAddress: activeContractsList.arbitrumGoerli['admin-repo'], - addresslistVotingRepoAddress: - activeContractsList.arbitrumGoerli['address-list-voting-repo'], - tokenVotingRepoAddress: - activeContractsList.arbitrumGoerli['token-voting-repo'], - multisigSetupAddress: activeContractsList.arbitrumGoerli.MultisigSetup, - adminSetupAddress: activeContractsList.arbitrumGoerli.AdminSetup, - addresslistVotingSetupAddress: - activeContractsList.arbitrumGoerli.AddresslistVotingSetup, - tokenVotingSetupAddress: - activeContractsList.arbitrumGoerli.TokenVotingSetup, - ensRegistryAddress: activeContractsList.arbitrumGoerli.ENSRegistry, - }, - [SupportedNetwork.LOCAL]: NOT_DEPLOYED, - }, -}; -export const ADDITIONAL_NETWORKS: Network[] = [ - { - name: 'sepolia', - chainId: 11155111, - }, - { - name: 'arbitrum', - chainId: 42161, - }, - { - name: 'arbitrumGoerli', - chainId: 421613, - }, - { - name: 'base', - chainId: 8453, - }, - { - name: 'baseGoerli', - chainId: 84531, - }, - { - name: 'local', - chainId: 31337, - }, -]; - -const Permissions = { - UPGRADE_PERMISSION: 'UPGRADE_PERMISSION', - SET_METADATA_PERMISSION: 'SET_METADATA_PERMISSION', - EXECUTE_PERMISSION: 'EXECUTE_PERMISSION', - WITHDRAW_PERMISSION: 'WITHDRAW_PERMISSION', - SET_SIGNATURE_VALIDATOR_PERMISSION: 'SET_SIGNATURE_VALIDATOR_PERMISSION', - SET_TRUSTED_FORWARDER_PERMISSION: 'SET_TRUSTED_FORWARDER_PERMISSION', - ROOT_PERMISSION: 'ROOT_PERMISSION', - CREATE_VERSION_PERMISSION: 'CREATE_VERSION_PERMISSION', - REGISTER_PERMISSION: 'REGISTER_PERMISSION', - REGISTER_DAO_PERMISSION: 'REGISTER_DAO_PERMISSION', - REGISTER_ENS_SUBDOMAIN_PERMISSION: 'REGISTER_ENS_SUBDOMAIN_PERMISSION', - MINT_PERMISSION: 'MINT_PERMISSION', - MERKLE_MINT_PERMISSION: 'MERKLE_MINT_PERMISSION', - MODIFY_ALLOWLIST_PERMISSION: 'MODIFY_ALLOWLIST_PERMISSION', - SET_CONFIGURATION_PERMISSION: 'SET_CONFIGURATION_PERMISSION', -}; - -const PermissionIds = Object.entries(Permissions).reduce( - (acc, [k, v]) => ({...acc, [k + '_ID']: keccak256(toUtf8Bytes(v))}), - {} as {[k: string]: string} -); -Object.freeze(Permissions); -export {Permissions}; -Object.freeze(PermissionIds); -export {PermissionIds}; export const IPFS_CID_REGEX = /^((Qm[1-9A-HJ-NP-Za-km-z]{44,})|(b[A-Za-z2-7]{58,}|B[A-Z2-7]{58,})|(z[1-9A-HJ-NP-Za-km-z]{48,})|(F[0-9A-F]{50,}))$/; diff --git a/sdk/src/context-core.ts b/sdk/src/context-core.ts deleted file mode 100644 index 8a8270d5..00000000 --- a/sdk/src/context-core.ts +++ /dev/null @@ -1,436 +0,0 @@ -import {GRAPHQL_NODES, IPFS_NODES, LIVE_CONTRACTS} from './constants'; -import { - InvalidGasEstimationFactorError, - UnsupportedNetworkError, - UnsupportedProtocolError, -} from './errors'; -import {InvalidAddressError} from './hex'; -import {DeployedAddressesArray} from './internal'; -import { - ContextParams, - ContextState, - OverriddenState, - SupportedNetwork, - SupportedNetworksArray, - SupportedVersion, -} from './types'; -import {getNetwork} from './utils'; -import {Client as IpfsClient} from '@aragon/sdk-ipfs'; -import {Signer} from '@ethersproject/abstract-signer'; -import {isAddress} from '@ethersproject/address'; -import {JsonRpcProvider, Network, Networkish} from '@ethersproject/providers'; -import {GraphQLClient} from 'graphql-request'; - -const DEFAULT_GAS_FEE_ESTIMATION_FACTOR = 0.625; -const supportedProtocols = ['https:']; -if (typeof process !== 'undefined' && process?.env?.TESTING) { - supportedProtocols.push('http:'); -} - -export abstract class ContextCore { - protected state: ContextState = {} as ContextState; - protected overriden: OverriddenState = { - daoFactoryAddress: false, - pluginSetupProcessorAddress: false, - multisigRepoAddress: false, - adminRepoAddress: false, - addresslistVotingRepoAddress: false, - tokenVotingRepoAddress: false, - multisigSetupAddress: false, - adminSetupAddress: false, - addresslistVotingSetupAddress: false, - tokenVotingSetupAddress: false, - ensRegistryAddress: false, - gasFeeEstimationFactor: false, - ipfsNodes: false, - graphqlNodes: false, - }; - // INTERNAL CONTEXT STATE - /** - * @param {Object} params - * - * @constructor - */ - constructor(params?: Partial) { - // set network to mainnet, overrided by the value of params - const mergedParams = Object.assign({network: 'mainnet'}, params); - this.set(mergedParams); - } - - set(contextParams: Partial) { - if (contextParams.network) { - this.state.network = ContextCore.resolveNetwork( - contextParams.network, - contextParams.ensRegistryAddress - ); - // once the network is resolved set default values - this.setNetworkDefaults(); - } - if (contextParams.signer) { - this.state.signer = contextParams.signer; - } - if ( - contextParams.web3Providers || - (Array.isArray(contextParams.web3Providers) && - contextParams.web3Providers.length) - ) { - this.state.web3Providers = ContextCore.resolveWeb3Providers( - contextParams.web3Providers, - this.state.network - ); - } - if (contextParams.graphqlNodes?.length) { - this.state.graphql = ContextCore.resolveGraphql( - contextParams.graphqlNodes - ); - this.overriden.graphqlNodes = true; - } - if (contextParams.ipfsNodes?.length) { - this.state.ipfs = ContextCore.resolveIpfs(contextParams.ipfsNodes); - this.overriden.ipfsNodes = true; - } - // Set all the available addresses - for (const address of DeployedAddressesArray) { - if (contextParams[address]) { - this.state[address] = contextParams[address] ?? ''; - this.overriden[address] = true; - } - } - - if (contextParams.gasFeeEstimationFactor) { - this.state.gasFeeEstimationFactor = - ContextCore.resolveGasFeeEstimationFactor( - contextParams.gasFeeEstimationFactor - ); - this.overriden.gasFeeEstimationFactor = true; - } - } - - private setNetworkDefaults() { - const networkName = this.network.name as SupportedNetwork; - if ( - !GRAPHQL_NODES[networkName]?.length || - !IPFS_NODES[networkName]?.length || - !LIVE_CONTRACTS[SupportedVersion.LATEST][networkName] - ) { - throw new UnsupportedNetworkError(networkName); - } - - if (!this.overriden.graphqlNodes) { - this.state.graphql = ContextCore.resolveGraphql( - GRAPHQL_NODES[networkName] - ); - } - - if (!this.overriden.ipfsNodes) { - this.state.ipfs = ContextCore.resolveIpfs(IPFS_NODES[networkName]); - } - - for (const address of DeployedAddressesArray) { - if (!this.overriden[address]) { - let defaultAddress = - LIVE_CONTRACTS[SupportedVersion.LATEST][networkName][address]; - // custom check for ensRegistryAddress - if (address === 'ensRegistryAddress' && !defaultAddress) { - defaultAddress = this.network.ensAddress; - } - if (defaultAddress) { - this.state[address] = defaultAddress; - } - } - } - - if (!this.overriden.gasFeeEstimationFactor) { - this.state.gasFeeEstimationFactor = DEFAULT_GAS_FEE_ESTIMATION_FACTOR; - } - } - - // GETTERS - - /** - * Getter for the network - * - * @var network - * - * @returns {Networkish} - * - * @public - */ - get network() { - return this.state.network; - } - /** - * Getter for the Signer - * - * @var signer - * - * @returns {Signer} - * - * @public - */ - get ensRegistryAddress(): string | undefined { - return this.state.ensRegistryAddress; - } - - /** - * Getter for the Signer - * - * @var signer - * - * @returns {Signer} - * - * @public - */ - get signer(): Signer { - return this.state.signer; - } - - /** - * Getter for the web3 providers - * - * @var web3Providers - * - * @returns {JsonRpcProvider[]} - * - * @public - */ - get web3Providers(): JsonRpcProvider[] { - return this.state.web3Providers || []; - } - - /** - * Getter for daoFactoryAddress property - * - * @var daoFactoryAddress - * - * @returns {string} - * - * @public - */ - get daoFactoryAddress(): string { - return this.state.daoFactoryAddress; - } - - /** - * Getter for pluginSetupProcessorAddress property - * @var pluginSetupProcessorAddress - * @returns {string} - * @public - */ - get pluginSetupProcessorAddress(): string { - return this.state.pluginSetupProcessorAddress; - } - /** - * Getter for multisigRepoAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get multisigRepoAddress(): string { - return this.state.multisigRepoAddress; - } - /** - * Getter for adminRepoAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get adminRepoAddress(): string { - return this.state.adminRepoAddress; - } - /** - * Getter for addresslistVotingRepoAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get addresslistVotingRepoAddress(): string { - return this.state.addresslistVotingRepoAddress; - } - /** - * Getter for tokenVotingRepoAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get tokenVotingRepoAddress(): string { - return this.state.tokenVotingRepoAddress; - } - /** - * Getter for multisigSetupAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get multisigSetupAddress(): string { - return this.state.multisigSetupAddress; - } - /** - * Getter for adminSetupAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get adminSetupAddress(): string { - return this.state.adminSetupAddress; - } - /** - * Getter for addresslistVotingSetupAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get addresslistVotingSetupAddress(): string { - return this.state.addresslistVotingSetupAddress; - } - /** - * Getter for tokenVotingSetupAddress property - * - * @readonly - * @type {string} - * @memberof ContextCore - */ - get tokenVotingSetupAddress(): string { - return this.state.tokenVotingSetupAddress; - } - - /** - * Getter for the gas fee reducer used in estimations - * - * @var gasFeeEstimationFactor - * - * @returns {number} - * - * @public - */ - get gasFeeEstimationFactor(): number { - return this.state.gasFeeEstimationFactor; - } - - /** - * Getter for the IPFS http client - * - * @var ipfs - * - * @returns {IpfsClient[]} - * - * @public - */ - get ipfs(): IpfsClient[] { - return this.state.ipfs; - } - - /** - * Getter for the GraphQL client - * - * @var graphql - * - * @returns {GraphQLClient[]} - * - * @public - */ - get graphql(): GraphQLClient[] { - return this.state.graphql; - } - - // INTERNAL HELPERS - private static resolveNetwork( - networkish: Networkish, - ensRegistryAddress?: string - ): Network { - const network = getNetwork(networkish); - const networkName = network.name as SupportedNetwork; - if (!SupportedNetworksArray.includes(networkName)) { - throw new UnsupportedNetworkError(networkName); - } - - if (ensRegistryAddress) { - if (!isAddress(ensRegistryAddress)) { - throw new InvalidAddressError(ensRegistryAddress); - } else { - network.ensAddress = ensRegistryAddress; - } - } - - if (!network.ensAddress) { - const ensAddress = - LIVE_CONTRACTS[SupportedVersion.LATEST][networkName].ensRegistryAddress; - if (!ensAddress) { - throw new UnsupportedNetworkError(networkName); - } - network.ensAddress = ensAddress; - } - return network; - } - - private static resolveWeb3Providers( - endpoints: string | JsonRpcProvider | (string | JsonRpcProvider)[], - network: Network - ): JsonRpcProvider[] { - if (Array.isArray(endpoints)) { - return endpoints.map(item => { - if (typeof item === 'string') { - const url = new URL(item); - if (!supportedProtocols.includes(url.protocol)) { - throw new UnsupportedProtocolError(url.protocol); - } - return new JsonRpcProvider(url.href, network); - } - return item; - }); - } else if (typeof endpoints === 'string') { - const url = new URL(endpoints); - if (!supportedProtocols.includes(url.protocol)) { - throw new UnsupportedProtocolError(url.protocol); - } - return [new JsonRpcProvider(url.href, network)]; - } else { - return [endpoints]; - } - } - - private static resolveIpfs( - configs: { - url: string; - headers?: Record; - }[] - ): IpfsClient[] { - const clients: IpfsClient[] = []; - configs.forEach(config => { - const url = new URL(config.url); - if (!supportedProtocols.includes(url.protocol)) { - throw new UnsupportedProtocolError(url.protocol); - } - clients.push(new IpfsClient(url, config.headers)); - }); - return clients; - } - - private static resolveGraphql(endpoints: {url: string}[]): GraphQLClient[] { - const clients: GraphQLClient[] = []; - endpoints.forEach(endpoint => { - const url = new URL(endpoint.url); - if (!supportedProtocols.includes(url.protocol)) { - throw new UnsupportedProtocolError(url.protocol); - } - clients.push(new GraphQLClient(url.href)); - }); - return clients; - } - - private static resolveGasFeeEstimationFactor( - gasFeeEstimationFactor: number - ): number { - if (gasFeeEstimationFactor < 0 || gasFeeEstimationFactor > 1) { - throw new InvalidGasEstimationFactorError(); - } - return gasFeeEstimationFactor; - } -} diff --git a/sdk/src/context.ts b/sdk/src/context.ts deleted file mode 100644 index b5368098..00000000 --- a/sdk/src/context.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {ContextCore} from './context-core'; -import {ContextParams} from './types'; - -// Basic implementation of the contex extending ContextCore -export class Context extends ContextCore { - constructor(params?: Partial) { - super(params); - } -} diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 328f4f95..944370f7 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -1,6 +1,5 @@ export * from './constants'; export * from './types'; -export * from './schemas'; export * from './validation'; export * from './multiuri'; export * from './ipfs'; @@ -10,10 +9,6 @@ export * from './promises'; export * from './errors'; // SDK -export * from './client-core'; -export * from './context-core'; -export * from './context'; -export * from './utils'; // From OSX export * from './bitmap'; diff --git a/sdk/src/internal/constants.ts b/sdk/src/internal/constants.ts deleted file mode 100644 index b0893d92..00000000 --- a/sdk/src/internal/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const ANY_ADDRESS = '0xffffffffffffffffffffffffffffffffffffffff'; diff --git a/sdk/src/internal/graphql-queries/index.ts b/sdk/src/internal/graphql-queries/index.ts deleted file mode 100644 index 862196f7..00000000 --- a/sdk/src/internal/graphql-queries/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './status'; -export * from './plugin'; diff --git a/sdk/src/internal/graphql-queries/plugin.ts b/sdk/src/internal/graphql-queries/plugin.ts deleted file mode 100644 index 6bd1abb3..00000000 --- a/sdk/src/internal/graphql-queries/plugin.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {gql} from 'graphql-request'; - -export const QueryIPlugin = gql` - query IPlugin($address: ID!, $where: IPlugin_filter!) { - iplugin(id: $address, where: $where) { - installations(where: {state: Installed}) { - appliedPreparation { - helpers - pluginRepo { - id - } - } - appliedVersion { - metadata - build - release { - release - } - } - } - } - } -`; diff --git a/sdk/src/internal/graphql-queries/status.ts b/sdk/src/internal/graphql-queries/status.ts deleted file mode 100644 index 42ed8438..00000000 --- a/sdk/src/internal/graphql-queries/status.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {gql} from 'graphql-request'; - -export const QueryStatus = gql` - { - _meta { - deployment - } - } -`; diff --git a/sdk/src/internal/index.ts b/sdk/src/internal/index.ts deleted file mode 100644 index 82a6b54e..00000000 --- a/sdk/src/internal/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './interfaces'; -export * from './modules'; -export * from './types'; diff --git a/sdk/src/internal/interfaces.ts b/sdk/src/internal/interfaces.ts deleted file mode 100644 index 412940f3..00000000 --- a/sdk/src/internal/interfaces.ts +++ /dev/null @@ -1,53 +0,0 @@ -// This file contains the definition of the low level network clients -import {GasFeeEstimation, SupportedNetwork} from '../types'; -import {DeployedAddresses} from './types'; -import {Client as IpfsClient, PinResponse} from '@aragon/sdk-ipfs'; -import {Signer} from '@ethersproject/abstract-signer'; -import {Contract, ContractInterface} from '@ethersproject/contracts'; -import {JsonRpcProvider} from '@ethersproject/providers'; -import {GraphQLClient} from 'graphql-request'; - -export interface IClientWeb3Core { - shiftProvider: () => void; - getSigner: () => Signer; - getConnectedSigner: () => Signer; - getProvider: () => JsonRpcProvider; - getNetworkName: () => SupportedNetwork; - getMaxFeePerGas: () => Promise; - isUp: () => Promise; - ensureOnline: () => Promise; - attachContract: (address: string, abi: ContractInterface) => Contract & T; - getAddress: (addressName: DeployedAddresses) => string; - getApproximateGasFee: (estimatedFee: bigint) => Promise; -} -export interface IClientIpfsCore { - getClient: () => IpfsClient; - shiftClient: () => void; - isUp: () => Promise; - ensureOnline: () => Promise; - add: (input: string | Uint8Array) => Promise; - pin: (input: string) => Promise; - fetchString: (cid: string) => Promise; - fetchBytes: (cid: string) => Promise; -} -export interface IClientGraphQLCore { - getClient: () => GraphQLClient; - shiftClient: () => void; - isUp: () => Promise; - ensureOnline: () => Promise; - request: ({ - query, - params, - name, - }: { - query: string; - params: {[key: string]: any}; - name?: string; - }) => Promise; -} - -export interface IClientCore { - web3: IClientWeb3Core; - ipfs: IClientIpfsCore; - graphql: IClientGraphQLCore; -} diff --git a/sdk/src/internal/modules/graphql.ts b/sdk/src/internal/modules/graphql.ts deleted file mode 100644 index 0d1e1a3e..00000000 --- a/sdk/src/internal/modules/graphql.ts +++ /dev/null @@ -1,110 +0,0 @@ -import {Context} from '../../context'; -import { - ClientNotInitializedError, - GraphQLError, - NoNodesAvailableError, -} from '../../errors'; -import {runAndRetry} from '../../promises'; -import {QueryStatus} from '../graphql-queries'; -import {IClientGraphQLCore} from '../interfaces'; -import {ClientError, GraphQLClient} from 'graphql-request'; - -export class GraphqlModule implements IClientGraphQLCore { - private clientIdx: number = -1; - private clients: GraphQLClient[] = []; - constructor(context: Context) { - if (context.graphql?.length) { - this.clients = context.graphql; - this.clientIdx = Math.floor(Math.random() * context.graphql.length); - } - } - /** - * Get the current graphql client - * @returns {GraphQLClient} - */ - public getClient(): GraphQLClient { - if (!this.clients.length || !this.clients[this.clientIdx]) { - throw new ClientNotInitializedError('graphql'); - } - return this.clients[this.clientIdx]; - } - - /** - * Starts using the next available Graphql endpoint - * @returns {void} - */ - public shiftClient(): void { - if (!this.clients.length) { - throw new ClientNotInitializedError('graphql'); - } else if (this.clients.length < 2) { - throw new NoNodesAvailableError('graphql'); - } - this.clientIdx = (this.clientIdx + 1) % this.clients.length; - } - - /** - * Checks if the current node is online - * @returns {Promise} - */ - public isUp(): Promise { - return this.getClient() - .request(QueryStatus) - .then(res => { - return !!res._meta?.deployment; - }) - .catch(() => { - return false; - }); - } - - /** - * Ensures that the graphql is online. - * If the current node is not online - * it will shift to the next one and - * repeat until it finds an online - * node. In the case that there are no - * nodes or none of them is available - * it will throw an error - * @returns {Promise} - */ - public async ensureOnline(): Promise { - if (!this.clients.length) { - throw new ClientNotInitializedError('graphql'); - } - for (let i = 0; i < this.clients.length; i++) { - if (await this.isUp()) return; - this.shiftClient(); - } - throw new NoNodesAvailableError('graphql'); - } - - public request({ - query, - params, - name, - }: { - query: string; - params: {[key: string]: any}; - name?: string; - }) { - if (!this.clients.length) { - throw new ClientNotInitializedError('graphql'); - } - let retries = this.clients.length; - return runAndRetry({ - func: () => this.getClient().request(query, params), - onFail: (e: Error) => { - if (e instanceof ClientError) { - // If the error code is not a 5XX means the - // error is not generated by the server - if (e.response.status < 500) { - throw new GraphQLError(name || '', e); - } - } - retries--; - this.shiftClient(); - }, - shouldRetry: () => retries > 0, - }); - } -} diff --git a/sdk/src/internal/modules/index.ts b/sdk/src/internal/modules/index.ts deleted file mode 100644 index dd80b40a..00000000 --- a/sdk/src/internal/modules/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './graphql'; -export * from './ipfs'; -export * from './web3'; diff --git a/sdk/src/internal/modules/ipfs.ts b/sdk/src/internal/modules/ipfs.ts deleted file mode 100644 index e10f6eb9..00000000 --- a/sdk/src/internal/modules/ipfs.ts +++ /dev/null @@ -1,111 +0,0 @@ -import {Context} from '../../context'; -import { - ClientNotInitializedError, - DataDecodingError, - IpfsError, - NoNodesAvailableError, -} from '../../errors'; -import {runAndRetry} from '../../promises'; -import {IClientIpfsCore} from '../interfaces'; -import {Client as IpfsClient, ClientError, PinResponse} from '@aragon/sdk-ipfs'; - -export class IPFSModule implements IClientIpfsCore { - private clientIdx: number = -1; - private clients: IpfsClient[] = []; - constructor(context: Context) { - // Storing client data in the private module's scope to prevent external mutation - if (context.ipfs?.length) { - this.clients = context.ipfs; - this.clientIdx = Math.floor(Math.random() * context.ipfs.length); - } - } - - public getClient(): IpfsClient { - if (!this.clients.length || !this.clients[this.clientIdx]) { - throw new ClientNotInitializedError('ipfs'); - } - return this.clients[this.clientIdx]; - } - - /** - * Starts using the next available IPFS endpoint - */ - public shiftClient(): void { - if (!this.clients.length) { - throw new ClientNotInitializedError('ipfs'); - } else if (this.clients?.length < 2) { - throw new NoNodesAvailableError('ipfs'); - } - this.clientIdx = (this.clientIdx + 1) % this.clients.length; - } - - /** Returns `true` if the current client is on line */ - public isUp(): Promise { - if (!this.clients?.length) return Promise.resolve(false); - return this.getClient() - .nodeInfo() - .then(() => true) - .catch(() => false); - } - - public async ensureOnline(): Promise { - if (!this.clients.length) { - throw new ClientNotInitializedError('ipfs'); - } - for (let i = 0; i < this.clients?.length; i++) { - if (await this.isUp()) return; - this.shiftClient(); - } - throw new NoNodesAvailableError('ipfs'); - } - - public getOnlineClient(): Promise { - return this.ensureOnline().then(() => this.getClient()); - } - - // IPFS METHODS - - public async add(input: string | Uint8Array): Promise { - return this.runAndRetryHelper(() => this.getClient().add(input)).then( - res => res.hash - ); - } - - public pin(input: string): Promise { - return this.runAndRetryHelper(() => this.getClient().pin(input)); - } - - public fetchBytes(cid: string): Promise { - return this.runAndRetryHelper(() => this.getClient().cat(cid)); - } - - private runAndRetryHelper(f: () => Promise): Promise { - if (!this.clients.length) { - throw new ClientNotInitializedError('ipfs'); - } - let retries = this.clients.length; - return runAndRetry({ - func: f, - onFail: (e: Error) => { - if (e instanceof ClientError) { - if (e.response.status < 500) { - // If the error code is not a 5XX means the - // error is not generated by the server - throw new IpfsError(e); - } - } - retries--; - this.shiftClient(); - }, - shouldRetry: () => retries > 0, - }); - } - - public fetchString(cid: string): Promise { - return this.fetchBytes(cid) - .then(bytes => new TextDecoder().decode(bytes)) - .catch(e => { - throw new DataDecodingError(e.message); - }); - } -} diff --git a/sdk/src/internal/modules/web3.ts b/sdk/src/internal/modules/web3.ts deleted file mode 100644 index 2815d1fd..00000000 --- a/sdk/src/internal/modules/web3.ts +++ /dev/null @@ -1,151 +0,0 @@ -import {Context} from '../../context'; -import { - CannotEstimateGasError, - InvalidContractAbiError, - NoNodesAvailableError, - NoProviderError, - NoSignerError, - UnsupportedNetworkError, -} from '../../errors'; -import {InvalidAddressError} from '../../hex'; -import { - GasFeeEstimation, - SupportedNetwork, - SupportedNetworksArray, -} from '../../types'; -import {IClientWeb3Core} from '../interfaces'; -import {DeployedAddresses} from '../types'; -import {Signer} from '@ethersproject/abstract-signer'; -import {isAddress} from '@ethersproject/address'; -import {Contract, ContractInterface} from '@ethersproject/contracts'; -import {JsonRpcProvider} from '@ethersproject/providers'; - -export class Web3Module implements IClientWeb3Core { - private static readonly PRECISION_FACTOR_BASE = 1000; - private providerIdx: number = -1; - private context: Context; - - constructor(context: Context) { - this.context = context; - this.providerIdx = Math.floor(Math.random() * context.web3Providers.length); - } - - /** Starts using the next available Web3 provider */ - public shiftProvider(): void { - if (!this.context.web3Providers.length) { - throw new NoProviderError(); - } else if (this.context.web3Providers.length <= 1) { - throw new NoNodesAvailableError('web3'); - } - this.providerIdx = - (this.providerIdx + 1) % this.context.web3Providers.length; - } - - /** Retrieves the current signer */ - public getSigner(): Signer { - if (!this.context.signer) { - throw new NoSignerError(); - } - return this.context.signer; - } - /** Returns the currently active network provider */ - public getProvider(): JsonRpcProvider { - if (!this.context.web3Providers[this.providerIdx]) { - throw new NoProviderError(); - } - return this.context.web3Providers[this.providerIdx]; - } - - /** Returns the currently active network */ - public getNetworkName(): SupportedNetwork { - const networkName = this.context.network.name as SupportedNetwork; - if (!SupportedNetworksArray.includes(networkName)) { - throw new UnsupportedNetworkError(networkName); - } - return networkName; - } - - /** Returns a signer connected to the current network provider */ - public getConnectedSigner(): Signer { - let signer = this.getSigner(); - if (!signer.provider) { - const provider = this.getProvider(); - signer = signer.connect(provider); - } - return signer; - } - - /** Returns whether the current provider is functional or not */ - public isUp(): Promise { - const provider = this.getProvider(); - return provider - .getNetwork() - .then(() => true) - .catch(() => false); - } - - public async ensureOnline(): Promise { - if (!this.context.web3Providers.length) { - throw new NoProviderError(); - } - - for (let i = 0; i < this.context.web3Providers.length; i++) { - if (await this.isUp()) return; - this.shiftProvider(); - } - throw new NoNodesAvailableError('web3'); - } - - /** - * Returns a contract instance at the given address - * - * @param address Contract instance address - * @param abi The Application Binary Inteface of the contract - * @return A contract instance attached to the given address - */ - public attachContract( - address: string, - abi: ContractInterface - ): Contract & T { - if (!address || !isAddress(address)) throw new InvalidAddressError(address); - else if (!abi) throw new InvalidContractAbiError(); - const signer = this.getConnectedSigner(); - return new Contract(address, abi, signer) as Contract & T; - } - - /** Calculates the expected maximum gas fee */ - public getMaxFeePerGas(): Promise { - return this.getConnectedSigner() - .getFeeData() - .then(feeData => { - if (!feeData.maxFeePerGas) { - throw new CannotEstimateGasError(); - } - return feeData.maxFeePerGas.toBigInt(); - }); - } - - public getApproximateGasFee(estimatedFee: bigint): Promise { - return this.getMaxFeePerGas().then(maxFeePerGas => { - const max = estimatedFee * maxFeePerGas; - - const factor = - this.context.gasFeeEstimationFactor * Web3Module.PRECISION_FACTOR_BASE; - - const average = - (max * BigInt(Math.trunc(factor))) / - BigInt(Web3Module.PRECISION_FACTOR_BASE); - - return {average, max}; - }); - } - - /** FRAMEWORK ADDRESSES */ - public getAddress(addressName: DeployedAddresses): string { - const address = this.context[addressName]; - if (!address || !isAddress(address)) { - throw new InvalidAddressError(address || 'undefined address'); - } - return address; - } -} diff --git a/sdk/src/internal/types.ts b/sdk/src/internal/types.ts deleted file mode 100644 index 0fa2df4a..00000000 --- a/sdk/src/internal/types.ts +++ /dev/null @@ -1,90 +0,0 @@ -import {Client as IpfsClient} from '@aragon/sdk-ipfs'; -import {Signer} from '@ethersproject/abstract-signer'; -import {JsonRpcProvider, Network, Networkish} from '@ethersproject/providers'; -import {GraphQLClient} from 'graphql-request'; - -// Create a readonly string array from the keys of NetworkDeployment -export const DeployedAddressesArray = [ - 'daoFactoryAddress', - 'pluginSetupProcessorAddress', - 'multisigRepoAddress', - 'adminRepoAddress', - 'addresslistVotingRepoAddress', - 'tokenVotingRepoAddress', - 'multisigSetupAddress', - 'adminSetupAddress', - 'addresslistVotingSetupAddress', - 'tokenVotingSetupAddress', - 'ensRegistryAddress', -] as const; -// export the type from the readonly string array -export type DeployedAddresses = (typeof DeployedAddressesArray)[number]; -// Override helper type -type Override = Omit & U; -export type NetworkDeployment = Override< - { - [address in DeployedAddresses]: string; - }, - {ensRegistryAddress?: string} ->; -// Context input parameters - -export type Web3ContextParams = - /** If any contract is not provided it will use the default from LIVE_CONTRACTS in the provided network */ - { - [address in DeployedAddresses]?: string; - } & { - /** Defaults to mainnet */ - network?: Networkish; - /** Required for Ethereum transactions to work */ - signer?: Signer; - /** Required for Ethereum connectivity to work */ - web3Providers?: string | JsonRpcProvider | (string | JsonRpcProvider)[]; - gasFeeEstimationFactor?: number; - }; -export type IpfsContextParams = { - /** If not provided uses default value */ - ipfsNodes?: {url: string; headers?: Record}[]; -}; -export type GraphQLContextParams = { - /** If not provided uses default value */ - graphqlNodes?: {url: string}[]; -}; - -export type Web3ContextState = Override< - { - [address in DeployedAddresses]: string; - }, - {ensRegistryAddress?: string} -> & { - network: Network; - signer: Signer; - web3Providers: JsonRpcProvider[]; - gasFeeEstimationFactor: number; -}; -export type IpfsContextState = { - ipfs: IpfsClient[]; -}; -export type GraphQLContextState = { - graphql: GraphQLClient[]; -}; - -export type SubgraphPluginInstallation = { - appliedVersion: SubgraphPluginVersion; - appliedPreparation: SubgraphPluginPreparation; -}; - -export type SubgraphPluginVersion = { - release: { - release: number; - }; - metadata: string; - build: number; -}; - -export type SubgraphPluginPreparation = { - helpers: string[]; - pluginRepo: { - id: string; - }; -}; diff --git a/sdk/src/schemas.ts b/sdk/src/schemas.ts deleted file mode 100644 index 54392cdb..00000000 --- a/sdk/src/schemas.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { - InvalidAddressOrEnsError, - InvalidCidError, - InvalidContractAbiError, - InvalidParameter, - InvalidSubdomainError, -} from './errors'; -import {ANY_ADDRESS} from './internal/constants'; -import {isEnsName, isIpfsUri, isSubdomain} from './validation'; -import {isAddress} from '@ethersproject/address'; -import {array, mixed, number, object, string} from 'yup'; - -export const BigintSchema = mixed().test( - 'isBigint', - new InvalidParameter('bigint').message, - value => typeof value === 'bigint' -); -export const AddressOrEnsSchema = string() - .notRequired() - .test('isAddressOrEns', new InvalidAddressOrEnsError().message, value => - value ? isAddress(value) || isEnsName(value) : true - ); -export const AddressOrEnsWithoutAnySchema = string() - .notRequired() - .test( - 'isAddressOrEnsWithoutAny', - new InvalidAddressOrEnsError().message, - value => - value - ? (isAddress(value) || isEnsName(value)) && value !== ANY_ADDRESS - : true - ); -export const VersionTagSchema = object({ - build: number().moreThan(0).required(), - release: number().moreThan(0).required(), -}); -export const AbiSchema = array() - .notRequired() - .test( - 'isValidAbi', - new InvalidContractAbiError().message, - // TODO: validate abi - () => true - ); -export const Uint8ArraySchema = mixed().test( - 'isUint8Array', - new InvalidParameter('Uint8Array').message, - value => (value ? value instanceof Uint8Array : true) -); -export const IpfsUriSchema = string().test( - 'isIpfsUri', - new InvalidCidError().message, - value => (value ? isIpfsUri(value) : true) -); -export const SubdomainSchema = string().test( - 'isSubdomain', - new InvalidSubdomainError().message, - value => (value ? isSubdomain(value) : true) -); - -export const PaginationSchema = object({ - skip: number().min(0).notRequired(), - limit: number().min(1).notRequired(), - direction: string().oneOf(['asc', 'desc']).notRequired(), -}); - -export const PrepareUninstallationSchema = object({ - daoAddressOrEns: AddressOrEnsSchema.required(), - pluginAddress: AddressOrEnsSchema.required(), - pluginInstallationIndex: number().notRequired().min(0), - uninstallationParams: array().notRequired(), - uninstallationAbi: AbiSchema.notRequired(), -}); -export const MultiTargetPermissionSchema = object({ - operation: number().required().oneOf([0, 1, 2]), - permissionId: string().required(), - where: AddressOrEnsWithoutAnySchema.required(), - who: AddressOrEnsWithoutAnySchema.required(), - condition: string().notRequired(), -}); - -export const PrepareInstallationSchema = object({ - daoAddressOrEns: AddressOrEnsSchema.required(), - pluginRepo: AddressOrEnsSchema.required(), - version: VersionTagSchema.notRequired(), - installationParams: array().notRequired(), - installationAbi: AbiSchema.notRequired(), -}); - -export const PluginInstallItemSchema = object({ - id: AddressOrEnsSchema.required(), - data: Uint8ArraySchema.required(), -}); - -export const ApplyUninstallationSchema = object({ - pluginAddress: AddressOrEnsSchema.required(), - pluginRepo: AddressOrEnsSchema.required(), - versionTag: VersionTagSchema.required(), - permissions: array(MultiTargetPermissionSchema).required(), -}); - -export const ApplyInstallationSchema = ApplyUninstallationSchema.concat( - object({ - helpers: array(AddressOrEnsSchema).required(), - }) -); diff --git a/sdk/src/types.ts b/sdk/src/types.ts index 4781e15e..e3f987cc 100644 --- a/sdk/src/types.ts +++ b/sdk/src/types.ts @@ -1,53 +1,3 @@ -import { - DeployedAddresses, - GraphQLContextParams, - GraphQLContextState, - IpfsContextParams, - IpfsContextState, - Web3ContextParams, - Web3ContextState, -} from './internal'; - -export type ContextParams = Web3ContextParams & - IpfsContextParams & - GraphQLContextParams; - -export type ContextState = Web3ContextState & - IpfsContextState & - GraphQLContextState; - -export type OverriddenState = { - [key in DeployedAddresses]: boolean; -} & { - gasFeeEstimationFactor: boolean; - ipfsNodes: boolean; - graphqlNodes: boolean; -}; - -export enum SupportedNetwork { - MAINNET = 'homestead', - GOERLI = 'goerli', - SEPOLIA = 'sepolia', - POLYGON = 'matic', - MUMBAI = 'maticmum', - BASE = 'base', - BASE_GOERLI = 'baseGoerli', - ARBITRUM = 'arbitrum', - ARBITRUM_GOERLI = 'arbitrumGoerli', - LOCAL = 'local', -} - -export const SupportedNetworksArray = Object.values(SupportedNetwork); - -/** - * Contains the payload passed to the global DAO factory so that - * plugins can be initialized - */ -export interface PluginInstallItem { - id: string; // ENS domain or address of the plugin's Repo - data: Uint8Array; -} - /** * Contains the supported plugin types */ @@ -57,20 +7,10 @@ export enum PluginType { Constructable = 2, } -export type GasFeeEstimation = { - average: bigint; - max: bigint; -}; - /** * Contains the payload passed to governance contracts, serializing * the actions to do upon approval */ -export type DaoAction = { - to: string; - value: bigint; - data: Uint8Array; -}; export type MetadataAbiInput = { name: string; @@ -80,63 +20,6 @@ export type MetadataAbiInput = { components?: MetadataAbiInput[]; }; -export type PrepareInstallationParams = { - daoAddressOrEns: string; - pluginRepo: string; - version?: { - build: number; - release: number; - }; - installationParams?: any[]; - installationAbi?: MetadataAbiInput[]; -}; - -export enum PrepareInstallationStep { - PREPARING = 'preparing', - DONE = 'done', -} - -export type PrepareInstallationStepValue = - | {key: PrepareInstallationStep.PREPARING; txHash: string} - | ({ - key: PrepareInstallationStep.DONE; - } & ApplyInstallationParams); - -export type ApplyInstallationParamsBase = { - permissions: MultiTargetPermission[]; - versionTag: VersionTag; - pluginRepo: string; - pluginAddress: string; -}; - -export type ApplyInstallationParams = ApplyInstallationParamsBase & { - helpers: string[]; -}; -export type DecodedApplyInstallationParams = ApplyInstallationParamsBase & { - helpersHash: string; -}; - -/* Uninstallation */ -export type PrepareUninstallationParams = { - daoAddressOrEns: string; - pluginAddress: string; - pluginInstallationIndex?: number; - uninstallationParams?: any[]; - uninstallationAbi?: string[]; -}; -export enum PrepareUninstallationSteps { - PREPARING = 'preparing', - DONE = 'done', -} -export type PrepareUninstallationStepValue = - | {key: PrepareUninstallationSteps.PREPARING; txHash: string} - | ({ - key: PrepareUninstallationSteps.DONE; - } & ApplyUninstallationParams); - -export type ApplyUninstallationParams = ApplyInstallationParamsBase; -export type DecodedApplyUninstallationParams = ApplyInstallationParamsBase; - export type VersionTag = { build: number; release: number; @@ -161,131 +44,3 @@ export type MultiTargetPermission = { condition?: string; permissionId: string; }; - -export type Pagination = { - skip?: number; - limit?: number; - direction?: SortDirection; -}; - -export enum SortDirection { - ASC = 'asc', - DESC = 'desc', -} - -export interface InterfaceParams { - id: string; - functionName: string; - hash: string; -} - -export enum TokenType { - NATIVE = 'native', - ERC20 = 'erc20', - ERC721 = 'erc721', - ERC1155 = 'erc1155', -} - -/** - * Contains the human-readable information about a proposal - */ -export type ProposalMetadata = { - title: string; - summary: string; - description: string; - resources: Array<{url: string; name: string}>; - media?: { - header?: string; - logo?: string; - }; -}; - -/** - * Contains the human-readable information about a proposal - */ -export type ProposalMetadataSummary = { - title: string; - summary: string; -}; - -export enum ProposalStatus { - ACTIVE = 'Active', - PENDING = 'Pending', - SUCCEEDED = 'Succeeded', - EXECUTED = 'Executed', - DEFEATED = 'Defeated', -} - -// Long version -export type ProposalBase = { - id: string; - dao: { - address: string; - name: string; - }; - creatorAddress: string; - metadata: ProposalMetadata; - startDate: Date; - endDate: Date; - creationDate: Date; - actions: DaoAction[]; - status: ProposalStatus; - creationBlockNumber: number; - executionDate: Date | null; - executionBlockNumber: number | null; - executionTxHash: string | null; -}; - -// Short version -export type ProposalListItemBase = { - id: string; - dao: { - address: string; - name: string; - }; - creatorAddress: string; - metadata: ProposalMetadataSummary; - startDate: Date; - endDate: Date; - status: ProposalStatus; -}; - -export type PrepareUpdateParams = { - pluginAddress: string; - daoAddressOrEns: string; - pluginInstallationIndex?: number; - newVersion: VersionTag; - updateParams?: any[]; - updateAbi?: MetadataAbiInput[]; - pluginRepo: string; -}; - -export enum PrepareUpdateStep { - PREPARING = 'preparing', - DONE = 'done', -} - -export type PrepareUpdateStepValue = - | {key: PrepareUpdateStep.PREPARING; txHash: string} - | ({ - key: PrepareUpdateStep.DONE; - } & ApplyUpdateParams); - -export type ApplyUpdateParamsBase = { - versionTag: VersionTag; - initData: Uint8Array; - pluginRepo: string; - pluginAddress: string; - permissions: MultiTargetPermission[]; -}; -export type ApplyUpdateParams = ApplyUpdateParamsBase & { - helpers: string[]; -}; -export type DecodedApplyUpdateParams = ApplyUpdateParamsBase & { - helpersHash: string; -}; -export enum SupportedVersion { - V1_0_0 = '1.0.0', - V1_3_0 = '1.3.0', - LATEST = '1.3.0', -} diff --git a/sdk/src/utils.ts b/sdk/src/utils.ts deleted file mode 100644 index dbb8c35b..00000000 --- a/sdk/src/utils.ts +++ /dev/null @@ -1,355 +0,0 @@ -import {ADDITIONAL_NETWORKS, LIVE_CONTRACTS} from './constants'; -import { - InstallationNotFoundError, - InvalidVersionError, - PluginInstallationPreparationError, - PluginUpdatePreparationError, - UnsupportedNetworkError, -} from './errors'; -import {findEventTopicLog} from './events'; -import {InvalidAddressError, bytesToHex, hexToBytes} from './hex'; -import { - IClientGraphQLCore, - IClientWeb3Core, - SubgraphPluginInstallation, -} from './internal'; -import {QueryIPlugin} from './internal/graphql-queries'; -import {getNamedTypesFromMetadata} from './metadata'; -import { - GasFeeEstimation, - PrepareInstallationParams, - PrepareInstallationStep, - PrepareInstallationStepValue, - PrepareUpdateParams, - PrepareUpdateStep, - PrepareUpdateStepValue, - SupportedNetwork, - SupportedVersion, -} from './types'; -import { - PluginRepo__factory, - PluginSetupProcessor, - PluginSetupProcessor__factory, -} from '@aragon/osx-ethers'; -import {FunctionFragment, Interface} from '@ethersproject/abi'; -import {defaultAbiCoder} from '@ethersproject/abi'; -import {isAddress} from '@ethersproject/address'; -import {Network} from '@ethersproject/networks'; -import { - getNetwork as ethersGetNetwork, - Networkish, -} from '@ethersproject/providers'; - -/** - * Gets a function fragment from encoded data - * - * @export - * @param {Uint8Array} data - * @param {string[]} availableFunctions - * @return {*} {FunctionFragment} - */ -export function getFunctionFragment( - data: Uint8Array, - availableFunctions: string[] -): FunctionFragment { - const hexBytes = bytesToHex(data); - const iface = new Interface(availableFunctions); - return iface.getFunction(hexBytes.substring(0, 10)); -} - -/** - * Gets the named types from a metadata abi input - * - * @export - * @param {IClientWeb3Core} web3 - * @param {PrepareInstallationParams} params - * @return {*} - */ -export async function prepareGenericInstallationEstimation( - web3: IClientWeb3Core, - params: PrepareInstallationParams -) { - const provider = web3.getProvider(); - if (!isAddress(params.pluginRepo)) { - throw new InvalidAddressError(params.pluginRepo); - } - const networkName = (await provider.getNetwork()).name as SupportedNetwork; - let version = params.version; - // if version is not specified install latest version - if (!version) { - const pluginRepo = PluginRepo__factory.connect(params.pluginRepo, provider); - const currentRelease = await pluginRepo.latestRelease(); - const latestVersion = await pluginRepo['getLatestVersion(uint8)']( - currentRelease - ); - version = latestVersion.tag; - } - // encode installation params - const {installationParams = [], installationAbi = []} = params; - const data = defaultAbiCoder.encode( - getNamedTypesFromMetadata(installationAbi), - installationParams - ); - // connect to psp contract - const pspContract = PluginSetupProcessor__factory.connect( - LIVE_CONTRACTS[SupportedVersion.LATEST][networkName] - .pluginSetupProcessorAddress, - provider - ); - - const gasEstimation = await pspContract.estimateGas.prepareInstallation( - params.daoAddressOrEns, - { - pluginSetupRef: { - pluginSetupRepo: params.pluginRepo, - versionTag: version, - }, - data, - } - ); - return web3.getApproximateGasFee(gasEstimation.toBigInt()); -} - -/** - * Prepares an installation of a plugin - * - * @export - * @param {IClientWeb3Core} web3 - * @param {(PrepareInstallationParams & { pluginSetupProcessorAddress: string })} params - * @return {*} {AsyncGenerator} - */ -export async function* prepareGenericInstallation( - web3: IClientWeb3Core, - params: PrepareInstallationParams & {pluginSetupProcessorAddress: string} -): AsyncGenerator { - const signer = web3.getConnectedSigner(); - if (!isAddress(params.pluginRepo)) { - throw new InvalidAddressError(params.pluginRepo); - } - let version = params.version; - // if version is not specified install latest version - if (!version) { - const pluginRepo = PluginRepo__factory.connect(params.pluginRepo, signer); - const currentRelease = await pluginRepo.latestRelease(); - const latestVersion = await pluginRepo['getLatestVersion(uint8)']( - currentRelease - ); - version = latestVersion.tag; - } - // encode installation params - const {installationParams = [], installationAbi = []} = params; - const data = defaultAbiCoder.encode( - getNamedTypesFromMetadata(installationAbi), - installationParams - ); - // connect to psp contract - const pspContract = PluginSetupProcessor__factory.connect( - params.pluginSetupProcessorAddress, - signer - ); - const tx = await pspContract.prepareInstallation(params.daoAddressOrEns, { - pluginSetupRef: { - pluginSetupRepo: params.pluginRepo, - versionTag: version, - }, - data, - }); - - yield { - key: PrepareInstallationStep.PREPARING, - txHash: tx.hash, - }; - const contractReceipt = await tx.wait(); - const event = findEventTopicLog( - contractReceipt, - PluginSetupProcessor__factory.createInterface(), - 'InstallationPrepared' - ); - const pluginAddress = event.args['plugin']; - const preparedSetupData = event.args['preparedSetupData']; - if (!(pluginAddress || preparedSetupData)) { - throw new PluginInstallationPreparationError(); - } - yield { - key: PrepareInstallationStep.DONE, - pluginAddress, - pluginRepo: params.pluginRepo, - versionTag: version, - permissions: preparedSetupData.permissions, - helpers: preparedSetupData.helpers, - }; -} - -/** - * Gets the parameters to be given when preparing an update - * - * @param {IClientGraphQLCore} graphql - * @param {PrepareUpdateParams} params - * @return {*} {Promise} - */ -async function getPrepareUpdateParams( - graphql: IClientGraphQLCore, - params: PrepareUpdateParams -): Promise { - type T = { - iplugin: {installations: SubgraphPluginInstallation[]}; - }; - const {iplugin} = await graphql.request({ - query: QueryIPlugin, - params: { - address: params.pluginAddress.toLowerCase(), - where: {dao: params.daoAddressOrEns.toLowerCase()}, - }, - name: 'plugin', - }); - - // filter specified installation - const {pluginInstallationIndex = 0} = params; - const selectedInstallation = iplugin.installations[pluginInstallationIndex]; - if (!selectedInstallation) { - throw new InstallationNotFoundError(); - } - // check if version is valid - if ( - params.newVersion.release !== - selectedInstallation.appliedVersion.release.release || - params.newVersion.build <= selectedInstallation.appliedVersion.build - ) { - throw new InvalidVersionError(); - } - // encode update params - const {updateParams = [], updateAbi = []} = params; - const data = defaultAbiCoder.encode( - getNamedTypesFromMetadata(updateAbi), - updateParams - ); - return { - currentVersionTag: { - build: selectedInstallation.appliedVersion.build, - release: selectedInstallation.appliedVersion.release.release, - }, - newVersionTag: params.newVersion, - pluginSetupRepo: params.pluginRepo, - setupPayload: { - plugin: params.pluginAddress, - currentHelpers: selectedInstallation.appliedPreparation.helpers, - data, - }, - }; -} - -/** - * Gets an estimation of the gas fee of preparing an update - * - * @export - * @param {IClientWeb3Core} web3 - * @param {IClientGraphQLCore} graphql - * @param {(PrepareUpdateParams & { pluginSetupProcessorAddress: string })} params - * @return {*} {Promise} - */ -export async function prepareGenericUpdateEstimation( - web3: IClientWeb3Core, - graphql: IClientGraphQLCore, - params: PrepareUpdateParams & {pluginSetupProcessorAddress: string} -): Promise { - const signer = web3.getConnectedSigner(); - const prepareUpdateParams = await getPrepareUpdateParams(graphql, params); - // connect to psp contract - const pspContract = PluginSetupProcessor__factory.connect( - params.pluginSetupProcessorAddress, - signer - ); - const gasEstimation = await pspContract.estimateGas.prepareUpdate( - params.daoAddressOrEns, - prepareUpdateParams - ); - return web3.getApproximateGasFee(gasEstimation.toBigInt()); -} - -export async function* prepareGenericUpdate( - web3: IClientWeb3Core, - graphql: IClientGraphQLCore, - params: PrepareUpdateParams & { - pluginSetupProcessorAddress: string; - } -): AsyncGenerator { - const signer = web3.getConnectedSigner(); - const prepareUpdateParams = await getPrepareUpdateParams(graphql, params); - // connect to psp contract - const pspContract = PluginSetupProcessor__factory.connect( - params.pluginSetupProcessorAddress, - signer - ); - - const tx = await pspContract.prepareUpdate( - params.daoAddressOrEns, - prepareUpdateParams - ); - yield { - key: PrepareUpdateStep.PREPARING, - txHash: tx.hash, - }; - const contractReceipt = await tx.wait(); - const event = findEventTopicLog( - contractReceipt, - PluginSetupProcessor__factory.createInterface(), - 'UpdatePrepared' - ); - const versionTag = event.args['versionTag']; - const preparedSetupData = event.args['preparedSetupData']; - const initData = event.args['initData']; - if ( - !versionTag || - versionTag.build !== params.newVersion.build || - versionTag.release !== params.newVersion.release || - !preparedSetupData || - !initData - ) { - throw new PluginUpdatePreparationError(); - } - yield { - key: PrepareUpdateStep.DONE, - versionTag, - pluginRepo: params.pluginRepo, - pluginAddress: params.pluginAddress, - initData: hexToBytes(initData), - permissions: preparedSetupData.permissions, - helpers: preparedSetupData.helpers, - }; -} - -/** - * Replacing function for ethers getNetwork that includes additional networks - * - * @export - * @param {Networkish} networkish - * @return {*} {Network} - */ -export function getNetwork(networkish: Networkish): Network { - let network: Network | undefined; - for (const nw of ADDITIONAL_NETWORKS) { - switch (typeof networkish) { - case 'string': - if (networkish === nw.name) { - network = nw; - } - break; - case 'number': - if (networkish === nw.chainId) { - network = nw; - } - break; - case 'object': - if (networkish.name === nw.name && networkish.chainId === nw.chainId) { - network = nw; - } - break; - default: - throw new UnsupportedNetworkError(networkish); - } - } - if (!network) { - network = ethersGetNetwork(networkish); - } - return network; -} diff --git a/sdk/test/schemas.test.ts b/sdk/test/schemas.test.ts deleted file mode 100644 index 53679922..00000000 --- a/sdk/test/schemas.test.ts +++ /dev/null @@ -1,781 +0,0 @@ -import { - AddressOrEnsSchema, - ApplyInstallationParams, - ApplyInstallationSchema, - ApplyUninstallationParams, - ApplyUninstallationSchema, - BigintSchema, - InvalidAddressOrEnsError, - InvalidCidError, - InvalidParameter, - InvalidSubdomainError, - IpfsUriSchema, - MultiTargetPermission, - MultiTargetPermissionSchema, - Pagination, - PaginationSchema, - PermissionIds, - PermissionOperationType, - PrepareInstallationParams, - PrepareInstallationSchema, - PrepareUninstallationParams, - PrepareUninstallationSchema, - SortDirection, - SubdomainSchema, - Uint8ArraySchema, - VersionTagSchema, -} from '../src'; -import { - TEST_ADDRESS, - TEST_ENS_NAME, - TEST_INVALID_ADDRESS, - TEST_INVALID_ENS_NAME, - TEST_INVALID_IPFS_URI, - TEST_INVALID_SUBDOMAIN, - TEST_IPFS_URI_V0, - TEST_IPFS_URI_V1, - TEST_SUBDOMAIN, -} from './constants'; -import {ValidationError} from 'yup'; - -describe('Test client schemas', () => { - describe('Test bigints', () => { - it('should validate a valid bigint', () => { - const number = BigInt(1); - BigintSchema.validateSync(number); - }); - it('should throw an error if the bigint is TEST_invalid', () => { - const number = 1; - expect(() => BigintSchema.validateSync(number)).toThrow( - new ValidationError(new InvalidParameter('bigint').message) - ); - }); - }); - - describe('Test address or ens', () => { - it('should validate a valid address', () => { - const address = TEST_ADDRESS; - AddressOrEnsSchema.strict().validateSync(address); - }); - it('should validate a valid ens', () => { - const ens = TEST_ENS_NAME; - AddressOrEnsSchema.strict().validateSync(ens); - }); - it('should throw an error if the address is invalid', () => { - const address = TEST_INVALID_ADDRESS; - expect(() => AddressOrEnsSchema.strict().validateSync(address)).toThrow( - new ValidationError(new InvalidAddressOrEnsError().message) - ); - }); - it('should throw an error if the ens is invalid', () => { - const ens = TEST_INVALID_ENS_NAME; - expect(() => AddressOrEnsSchema.strict().validateSync(ens)).toThrow( - new ValidationError(new InvalidAddressOrEnsError().message) - ); - }); - }); - - describe('Test version tag', () => { - it('should validate a valid version tag', () => { - const versionTag = { - release: 1, - build: 1, - }; - VersionTagSchema.strict().validateSync(versionTag); - }); - it('should throw an error if the release is invalid', () => { - const versionTag = { - release: 0, - build: 1, - }; - expect(() => VersionTagSchema.strict().validateSync(versionTag)).toThrow( - new ValidationError('release must be greater than 0') - ); - }); - it('should throw an error if the release is invalid', () => { - const versionTag = { - release: 1, - build: 0, - }; - expect(() => VersionTagSchema.strict().validateSync(versionTag)).toThrow( - new ValidationError('build must be greater than 0') - ); - }); - it('should throw an error if the build is missing', () => { - const versionTag = { - release: 1, - }; - expect(() => VersionTagSchema.strict().validateSync(versionTag)).toThrow( - new ValidationError('build is a required field') - ); - }); - it('should throw an error if the release is missing', () => { - const versionTag = { - build: 1, - }; - expect(() => VersionTagSchema.strict().validateSync(versionTag)).toThrow( - new ValidationError('release is a required field') - ); - }); - }); - - test.todo('Abi Schema'); - - describe('Test Uint8Array', () => { - it('should validate a valid Uint8Array', () => { - const uint8Array = new Uint8Array(); - Uint8ArraySchema.strict().validateSync(uint8Array); - }); - it('should throw an error if the Uint8Array is invalid', () => { - const uint8Array: number[] = []; - expect(() => Uint8ArraySchema.strict().validateSync(uint8Array)).toThrow( - new ValidationError(new InvalidParameter('Uint8Array').message) - ); - }); - }); - - describe('Test IpfsCid', () => { - it('should validate a valid v0 ipfs CID', () => { - const ipfsUri = TEST_IPFS_URI_V0; - IpfsUriSchema.strict().validateSync(ipfsUri); - }); - it('should validate a valid v1 ipfs CID', () => { - const ipfsUri = TEST_IPFS_URI_V1; - IpfsUriSchema.strict().validateSync(ipfsUri); - }); - it('should throw an error if the ipfs CID is invalid', () => { - const ipfsUri = TEST_INVALID_IPFS_URI; - expect(() => IpfsUriSchema.strict().validateSync(ipfsUri)).toThrow( - new ValidationError(new InvalidCidError().message) - ); - }); - }); - describe('Test Subdomain', () => { - it('should validate a valid subdomain', () => { - const subdomain = TEST_SUBDOMAIN; - SubdomainSchema.strict().validateSync(subdomain); - }); - it('should throw an error if the subdomain is invalid', () => { - const subdomain = TEST_INVALID_SUBDOMAIN; - expect(() => SubdomainSchema.strict().validateSync(subdomain)).toThrow( - new ValidationError(new InvalidSubdomainError().message) - ); - }); - }); - - describe('Test Pagination', () => { - it('should validate a valid Pagination', () => { - const pagination: Pagination = { - skip: 0, - limit: 1, - direction: SortDirection.ASC, - }; - PaginationSchema.strict().validateSync(pagination); - }); - it('should validate a valid Pagination without optional params', () => { - const pagination: Pagination = {}; - PaginationSchema.strict().validateSync(pagination); - }); - it('should throw an error if the skip is invalid', () => { - const pagination: Pagination = { - skip: -1, - limit: 1, - }; - expect(() => PaginationSchema.strict().validateSync(pagination)).toThrow( - new ValidationError('skip must be greater than or equal to 0') - ); - }); - it('should throw an error if the limit is invalid', () => { - const pagination: Pagination = { - skip: 0, - limit: 0, - }; - expect(() => PaginationSchema.strict().validateSync(pagination)).toThrow( - new ValidationError('limit must be greater than or equal to 1') - ); - }); - it('should throw an error if the direction is invalid', () => { - const pagination = { - skip: 0, - limit: 1, - direction: 'invalid', - }; - expect(() => PaginationSchema.strict().validateSync(pagination)).toThrow( - new ValidationError( - 'direction must be one of the following values: asc, desc' - ) - ); - }); - }); - - describe('Test MultiTargetPermission', () => { - it('should validate a valid MultiTargetPermission', () => { - const multiTargetPermission: MultiTargetPermission = { - operation: PermissionOperationType.GRANT, - where: TEST_ADDRESS, - who: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - condition: TEST_ADDRESS, - }; - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission); - }); - it('should validate a valid MultiTargetPermission without optional params', () => { - const multiTargetPermission: MultiTargetPermission = { - operation: PermissionOperationType.GRANT, - where: TEST_ADDRESS, - who: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission); - }); - it('should throw an error if the operation is invalid', () => { - const multiTargetPermission = { - operation: 3, - where: TEST_ADDRESS, - who: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow( - new ValidationError( - 'operation must be one of the following values: 0, 1, 2' - ) - ); - }); - it('should throw an error if the operation is missing', () => { - const multiTargetPermission = { - where: TEST_ADDRESS, - who: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError('operation is a required field')); - }); - it('should throw an error if the where is invalid', () => { - const multiTargetPermission = { - operation: PermissionOperationType.GRANT, - where: TEST_INVALID_ADDRESS, - who: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the who is invalid', () => { - const multiTargetPermission = { - operation: PermissionOperationType.GRANT, - where: TEST_ADDRESS, - who: TEST_INVALID_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the permissionId is missing', () => { - const multiTargetPermission = { - operation: PermissionOperationType.GRANT, - where: TEST_ADDRESS, - who: TEST_ADDRESS, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError('permissionId is a required field')); - }); - it('should throw if the where is missing', () => { - const multiTargetPermission = { - operation: PermissionOperationType.GRANT, - who: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError('where is a required field')); - }); - it('should throw if the who is missing', () => { - const multiTargetPermission = { - operation: PermissionOperationType.GRANT, - where: TEST_ADDRESS, - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError('who is a required field')); - }); - it('should throw if the operation is missing', () => { - const multiTargetPermission = { - permissionId: PermissionIds.EXECUTE_PERMISSION_ID, - where: TEST_ADDRESS, - who: TEST_ADDRESS, - }; - expect(() => - MultiTargetPermissionSchema.strict().validateSync(multiTargetPermission) - ).toThrow(new ValidationError('operation is a required field')); - }); - }); - - describe('Test PrepareInstallation', () => { - it('should validate a valid PrepareInstallation', () => { - const prepareInstallationParams: PrepareInstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - version: { - release: 1, - build: 1, - }, - installationParams: [], - installationAbi: [], - }; - PrepareInstallationSchema.strict().validateSync( - prepareInstallationParams - ); - }); - it('should validate a valid PrepareInstallation without optional params', () => { - const prepareInstallationParams: PrepareInstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - }; - - PrepareInstallationSchema.strict().validateSync( - prepareInstallationParams - ); - }); - it('should throw an error if the daoAddressOrEns is missing', () => { - const prepareInstallationParams = { - pluginRepo: TEST_ADDRESS, - }; - expect(() => - PrepareInstallationSchema.strict().validateSync( - prepareInstallationParams - ) - ).toThrow(new ValidationError('daoAddressOrEns is a required field')); - }); - it('should throw an error if the pluginRepo is missing', () => { - const prepareInstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - }; - expect(() => - PrepareInstallationSchema.strict().validateSync( - prepareInstallationParams - ) - ).toThrow(new ValidationError('pluginRepo is a required field')); - }); - it('should throw an error if the daoAddressOrEns is invalid', () => { - const prepareInstallationParams: PrepareInstallationParams = { - daoAddressOrEns: TEST_INVALID_ADDRESS, - pluginRepo: TEST_ADDRESS, - }; - expect(() => - PrepareInstallationSchema.strict().validateSync( - prepareInstallationParams - ) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the pluginRepo is invalid', () => { - const prepareInstallationParams: PrepareInstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginRepo: TEST_INVALID_ADDRESS, - }; - expect(() => - PrepareInstallationSchema.strict().validateSync( - prepareInstallationParams - ) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - }); - describe('Test PrepareUninstallation', () => { - it('should validate a valid PrepareUninstallation', () => { - const prepareUninstallationParams: PrepareUninstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginAddress: TEST_ADDRESS, - pluginInstallationIndex: 0, - uninstallationAbi: [], - uninstallationParams: [], - }; - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ); - }); - it('should validate a valid PrepareUninstallation without optional params', () => { - const prepareUninstallationParams: PrepareUninstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginAddress: TEST_ADDRESS, - pluginInstallationIndex: 0, - }; - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ); - }); - it('should throw an error if the daoAddressOrEns is missing', () => { - const prepareUninstallationParams = { - pluginAddress: TEST_ADDRESS, - }; - expect(() => - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ) - ).toThrow(new ValidationError('daoAddressOrEns is a required field')); - }); - it('should throw an error if the pluginAddress is missing', () => { - const prepareUninstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - }; - expect(() => - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ) - ).toThrow(new ValidationError('pluginAddress is a required field')); - }); - it('should throw an error if the pluginInstallationIndex is invalid', () => { - const prepareUninstallationParams: PrepareUninstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginAddress: TEST_ADDRESS, - pluginInstallationIndex: -1, - }; - expect(() => - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ) - ).toThrow( - new ValidationError( - 'pluginInstallationIndex must be greater than or equal to 0' - ) - ); - }); - it('should throw an error if the daoAddressOrEns is invalid', () => { - const prepareUninstallationParams: PrepareUninstallationParams = { - daoAddressOrEns: TEST_INVALID_ADDRESS, - pluginAddress: TEST_ADDRESS, - pluginInstallationIndex: 0, - }; - expect(() => - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the pluginAddress is invalid', () => { - const prepareUninstallationParams: PrepareUninstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginAddress: TEST_INVALID_ADDRESS, - pluginInstallationIndex: 0, - }; - expect(() => - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the uninstallationParams is invalid', () => { - const prepareUninstallationParams = { - daoAddressOrEns: TEST_ADDRESS, - pluginAddress: TEST_ADDRESS, - uninstallationParams: {}, - }; - expect(() => - PrepareUninstallationSchema.strict().validateSync( - prepareUninstallationParams - ) - ).toThrow( - new ValidationError( - 'uninstallationParams must be a `array` type, but the final value was: `{}`.' - ) - ); - }); - test.todo('should throw an error if the uninstallationAbi is invalid'); - }); - describe('Test ApplyUninstallation', () => { - it('should validate a valid ApplyUninstallation', () => { - const applyUninstallationParams: ApplyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - }; - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ); - }); - it('should throw an error if the pluginAddress is missing', () => { - const applyUninstallationParams = { - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError('pluginAddress is a required field')); - }); - it('should throw an error if the pluginRepo is missing', () => { - const applyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError('pluginRepo is a required field')); - }); - it('should throw an error if the versionTag is missing', () => { - const applyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - permissions: [], - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError('versionTag is a required field')); - }); - it('should throw an error if the permissions is missing', () => { - const applyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError('permissions is a required field')); - }); - it('should throw an error if the pluginAddress is invalid', () => { - const applyUninstallationParams: ApplyUninstallationParams = { - pluginAddress: TEST_INVALID_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the pluginRepo is invalid', () => { - const applyUninstallationParams: ApplyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_INVALID_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the versionTag is invalid', () => { - const applyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 0, - release: 1, - }, - permissions: [], - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow(new ValidationError('versionTag.build must be greater than 0')); - }); - it('should throw an error if the permissions is invalid', () => { - const applyUninstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: {}, - }; - expect(() => - ApplyUninstallationSchema.strict().validateSync( - applyUninstallationParams - ) - ).toThrow( - new ValidationError( - 'permissions must be a `array` type, but the final value was: `{}`.' - ) - ); - }); - }); - describe('Test ApplyInstallation', () => { - it('should validate a valid ApplyInstallation', () => { - const applyInstallationParams: ApplyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - helpers: [], - }; - ApplyInstallationSchema.strict().validateSync(applyInstallationParams); - }); - it('should throw an error if the pluginAddress is missing', () => { - const applyInstallationParams = { - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError('pluginAddress is a required field')); - }); - it('should throw an error if the pluginRepo is missing', () => { - const applyInstallationParams = { - pluginAddress: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError('pluginRepo is a required field')); - }); - it('should throw an error if the versionTag is missing', () => { - const applyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - permissions: [], - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError('versionTag is a required field')); - }); - it('should throw an error if the permissions is missing', () => { - const applyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError('permissions is a required field')); - }); - it('should throw an error if the helpers is missing', () => { - const applyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError('helpers is a required field')); - }); - it('should throw an error if the pluginAddress is invalid', () => { - const applyInstallationParams: ApplyInstallationParams = { - pluginAddress: TEST_INVALID_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the pluginRepo is invalid', () => { - const applyInstallationParams: ApplyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_INVALID_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow(new ValidationError(new InvalidAddressOrEnsError().message)); - }); - it('should throw an error if the permissions is invalid', () => { - const applyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: {}, - helpers: [], - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow( - new ValidationError( - 'permissions must be a `array` type, but the final value was: `{}`.' - ) - ); - }); - it('should throw an error if the helpers is invalid', () => { - const applyInstallationParams = { - pluginAddress: TEST_ADDRESS, - pluginRepo: TEST_ADDRESS, - versionTag: { - build: 1, - release: 1, - }, - permissions: [], - helpers: {}, - }; - expect(() => - ApplyInstallationSchema.strict().validateSync(applyInstallationParams) - ).toThrow( - new ValidationError( - 'helpers must be a `array` type, but the final value was: `{}`.' - ) - ); - }); - }); -}); diff --git a/sdk/test/unit/client.test.ts b/sdk/test/unit/client.test.ts deleted file mode 100644 index 174bfad6..00000000 --- a/sdk/test/unit/client.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { - ClientCore, - ContextCore, - ContextParams, - NoProviderError, - NoSignerError, -} from '../../src'; -import { - DEFAULT_IPFS_ENDPOINTS, - TEST_WALLET, - TEST_WALLET_ADDRESS, - web3endpoints, -} from '../constants'; -import {Wallet} from '@ethersproject/wallet'; - -class TestContext extends ContextCore { - constructor(params?: Partial) { - super(params); - } -} - -class TestClient extends ClientCore { - constructor(context: TestContext) { - super(context); - } -} - -describe('Test an extended client', () => { - it('Should create a client with the default context parameters', async () => { - const contextParams: ContextParams = { - signer: new Wallet(TEST_WALLET), - web3Providers: web3endpoints.working, - }; - const ctx = new TestContext(contextParams); - const client = new TestClient(ctx); - expect(client).toBeDefined(); - expect(ctx).toBeDefined(); - expect(client.web3).toBeDefined(); - expect(client.ipfs).toBeDefined(); - expect(client.graphql).toBeDefined(); - const provider = client.web3.getProvider(); - expect(provider).toBeDefined(); - - const networkName = client.web3.getNetworkName(); - expect(networkName).toBe('homestead'); - - const signer = client.web3.getConnectedSigner(); - expect(signer).toBeDefined(); - expect(await signer.getAddress()).toBe(TEST_WALLET_ADDRESS); - - const ipfsClient = client.ipfs.getClient(); - expect(ipfsClient).toBeDefined(); - expect(DEFAULT_IPFS_ENDPOINTS.includes(ipfsClient.url.toString())).toBe( - true - ); - - const graphqlClient = client.graphql.getClient(); - expect(graphqlClient).toBeDefined(); - }); - - it('Should create a client without signer and provider', async () => { - const ctx = new TestContext(); - const client = new TestClient(ctx); - expect(client).toBeDefined(); - expect(ctx).toBeDefined(); - expect(client.web3).toBeDefined(); - expect(client.ipfs).toBeDefined(); - expect(client.graphql).toBeDefined(); - - const networkName = client.web3.getNetworkName(); - expect(networkName).toBe('homestead'); - - expect(() => client.web3.getProvider()).toThrowError(NoProviderError); - expect(() => client.web3.getConnectedSigner()).toThrowError(NoSignerError); - - const ipfsClient = client.ipfs.getClient(); - expect(ipfsClient).toBeDefined(); - expect(DEFAULT_IPFS_ENDPOINTS.includes(ipfsClient.url.toString())).toBe( - true - ); - - const graphqlClient = client.graphql.getClient(); - expect(graphqlClient).toBeDefined(); - }); - - it('Should create a client with baseGoerli context parameters', async () => { - const contextParams: ContextParams = { - network: 'baseGoerli', - signer: new Wallet(TEST_WALLET), - web3Providers: 'https://goerli.base.org', - }; - const ctx = new TestContext(contextParams); - const client = new TestClient(ctx); - expect(client).toBeDefined(); - expect(ctx).toBeDefined(); - expect(client.web3).toBeDefined(); - expect(client.ipfs).toBeDefined(); - expect(client.graphql).toBeDefined(); - - const networkName = client.web3.getNetworkName(); - expect(networkName).toBe('baseGoerli'); - const signer = client.web3.getConnectedSigner(); - expect(signer).toBeDefined(); - expect(await signer.getAddress()).toBe(TEST_WALLET_ADDRESS); - - const ipfsClient = client.ipfs.getClient(); - expect(ipfsClient).toBeDefined(); - expect(DEFAULT_IPFS_ENDPOINTS.includes(ipfsClient.url.toString())).toBe( - true - ); - - const graphqlClient = client.graphql.getClient(); - expect(graphqlClient).toBeDefined(); - }); -}); diff --git a/sdk/test/unit/context.test.ts b/sdk/test/unit/context.test.ts deleted file mode 100644 index af8edd36..00000000 --- a/sdk/test/unit/context.test.ts +++ /dev/null @@ -1,295 +0,0 @@ -import { - ContextCore, - ContextParams, - GRAPHQL_NODES, - IPFS_NODES, - LIVE_CONTRACTS, - SupportedVersion, -} from '../../src'; -import {ADDRESS_ONE, TEST_WALLET, web3endpoints} from '../constants'; -import {Client as IpfsClient} from '@aragon/sdk-ipfs'; -import {JsonRpcProvider} from '@ethersproject/providers'; -import {Wallet} from '@ethersproject/wallet'; -import {GraphQLClient} from 'graphql-request'; - -class TestContext extends ContextCore { - constructor(params?: Partial) { - super(params); - } -} - -let contextParams: ContextParams; - -describe('Context instances', () => { - beforeEach(() => { - contextParams = { - network: 'mainnet', - signer: new Wallet(TEST_WALLET), - daoFactoryAddress: '0x1234', - web3Providers: web3endpoints.working, - gasFeeEstimationFactor: 0.1, - graphqlNodes: [], - ipfsNodes: [], - }; - }); - it('Should create an empty context and have default values', () => { - const context = new TestContext(); - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toBe('homestead'); - expect(context.network.chainId).toBe(1); - expect(context.daoFactoryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].homestead.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toBe(context.network.ensAddress); - expect(context.gasFeeEstimationFactor).toBe(0.625); - expect(context.web3Providers.length).toBe(0); - expect(context.ipfs.length).toBe(IPFS_NODES.homestead.length); - expect(context.graphql.length).toBe(GRAPHQL_NODES.homestead.length); - context.web3Providers.map(provider => { - expect(provider).toBeInstanceOf(JsonRpcProvider); - }); - context.ipfs.map(ipfsClient => { - expect(ipfsClient).toBeInstanceOf(IpfsClient); - }); - context.graphql.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - }); - it('Should create a context and have the correct values', () => { - const context = new TestContext(contextParams); - - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toBe('homestead'); - expect(context.network.chainId).toBe(1); - expect(context.daoFactoryAddress).toBe(contextParams.daoFactoryAddress); - expect(context.ensRegistryAddress).toBe(context.network.ensAddress); - expect(context.gasFeeEstimationFactor).toBe( - contextParams.gasFeeEstimationFactor - ); - context.web3Providers.map(provider => - expect(provider).toBeInstanceOf(JsonRpcProvider) - ); - context.ipfs.map(ipfsClient => - expect(ipfsClient).toBeInstanceOf(IpfsClient) - ); - context.graphql.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - }); - it('Should set a new context and have the correct values', () => { - const context = new TestContext(contextParams); - contextParams = { - network: 'goerli', - signer: new Wallet(TEST_WALLET), - daoFactoryAddress: '0x2345', - web3Providers: web3endpoints.working, - gasFeeEstimationFactor: 0.1, - ipfsNodes: [{url: 'https://localhost', headers: {}}], - graphqlNodes: [{url: 'https://localhost'}], - }; - context.set(contextParams); - - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toEqual('goerli'); - expect(context.network.chainId).toEqual(5); - expect(context.signer).toBeInstanceOf(Wallet); - expect(context.daoFactoryAddress).toEqual('0x2345'); - context.web3Providers?.map(provider => - expect(provider).toBeInstanceOf(JsonRpcProvider) - ); - context.ipfs?.map(ipfsClient => - expect(ipfsClient).toBeInstanceOf(IpfsClient) - ); - context.graphql?.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - expect(context.gasFeeEstimationFactor).toEqual(0.1); - }); - it('Should create a context in goerli, update the network and update all the parameters automatically', () => { - const context = new TestContext({ - network: 'goerli', - web3Providers: 'https://eth-goerli.g.alchemy.com/v2/demo', - }); - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toBe('goerli'); - expect(context.network.chainId).toBe(5); - expect(context.daoFactoryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].goerli.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toBe(context.network.ensAddress); - expect(context.gasFeeEstimationFactor).toBe(0.625); - expect(context.web3Providers.length).toBe(1); - expect(context.ipfs.length).toBe(IPFS_NODES.goerli.length); - expect(context.graphql.length).toBe(GRAPHQL_NODES.goerli.length); - context.web3Providers.map(provider => { - expect(provider).toBeInstanceOf(JsonRpcProvider); - }); - context.ipfs.map(ipfsClient => { - expect(ipfsClient).toBeInstanceOf(IpfsClient); - }); - context.graphql.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - context.set({ - network: 'matic', - web3Providers: 'https://polygon-rpc.com/', - }); - expect(context.network.name).toBe('matic'); - expect(context.network.chainId).toBe(137); - expect(context.daoFactoryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.ensRegistryAddress - ); - expect(context.gasFeeEstimationFactor).toBe(0.625); - expect(context.web3Providers.length).toBe(1); - expect(context.ipfs.length).toBe(IPFS_NODES.matic.length); - expect(context.graphql.length).toBe(GRAPHQL_NODES.matic.length); - context.web3Providers.map(provider => { - expect(provider).toBeInstanceOf(JsonRpcProvider); - }); - context.ipfs.map(ipfsClient => { - expect(ipfsClient).toBeInstanceOf(IpfsClient); - }); - context.graphql.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - }); - it('Should create an empty context, update the network and update all the parameters automatically', () => { - const context = new TestContext(); - expect(context).toBeInstanceOf(TestContext); - context.set({ - network: 'matic', - web3Providers: 'https://polygon-rpc.com/', - }); - expect(context.network.name).toBe('matic'); - expect(context.network.chainId).toBe(137); - expect(context.daoFactoryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.ensRegistryAddress - ); - expect(context.gasFeeEstimationFactor).toBe(0.625); - expect(context.web3Providers.length).toBe(1); - expect(context.ipfs.length).toBe(IPFS_NODES.matic.length); - expect(context.graphql.length).toBe(GRAPHQL_NODES.matic.length); - context.web3Providers.map(provider => { - expect(provider).toBeInstanceOf(JsonRpcProvider); - }); - context.ipfs.map(ipfsClient => { - expect(ipfsClient).toBeInstanceOf(IpfsClient); - }); - context.graphql.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - }); - it('Should Change the network and update all the parameters', () => { - const context = new TestContext(); - context.set({ - ensRegistryAddress: ADDRESS_ONE, - graphqlNodes: [ - { - url: 'https://example.com/1', - }, - { - url: 'https://example.com/2', - }, - { - url: 'https://example.com/3', - }, - ], - }); - // Make sure that the prvious propertis are not modified - // with the networ change becaouse now they are on manual - // mode - context.set({network: 'matic'}); - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toBe('matic'); - expect(context.network.chainId).toBe(137); - expect(context.daoFactoryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toBe(ADDRESS_ONE); - expect(context.gasFeeEstimationFactor).toBe(0.625); - expect(context.web3Providers.length).toBe(0); - expect(context.ipfs.length).toBe(IPFS_NODES.matic.length); - expect(context.graphql.length).toBe(3); - context.web3Providers.map(provider => { - expect(provider).toBeInstanceOf(JsonRpcProvider); - }); - context.ipfs.map(ipfsClient => { - expect(ipfsClient).toBeInstanceOf(IpfsClient); - }); - context.graphql.map(graphqlClient => - expect(graphqlClient).toBeInstanceOf(GraphQLClient) - ); - }); - it('Should create a context with invalid network and fail', () => { - contextParams.network = 'notexistingnetwork'; - - expect(() => { - new TestContext(contextParams); - }).toThrow(); - }); - it('Should create a context with invalid gas fee estimation factor and fail', () => { - contextParams.gasFeeEstimationFactor = 1.1; - - expect(() => { - new TestContext(contextParams); - }).toThrow(); - }); - it('Should create a context with the correct DAOFactory address from the core-contracts-package', () => { - contextParams.daoFactoryAddress = ''; - contextParams.network = 'matic'; - contextParams.web3Providers = ['https://polygon-rpc.com/']; - const context = new TestContext(contextParams); - - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toEqual('matic'); - context.web3Providers?.map(provider => - provider.getNetwork().then(nw => { - expect(nw.chainId).toEqual(137); - expect(nw.name).toEqual('matic'); - expect(nw.ensAddress).toEqual( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.ensRegistryAddress - ); - }) - ); - expect(context.daoFactoryAddress).toEqual( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toEqual( - LIVE_CONTRACTS[SupportedVersion.LATEST].matic.ensRegistryAddress - ); - }); - it('Should create a context with baseGoerli as network and have the correct values', () => { - const contextParams = { - network: 'baseGoerli', - web3Providers: 'https://goerli.base.org', - }; - const context = new TestContext(contextParams); - expect(context).toBeInstanceOf(TestContext); - expect(context.network.name).toBe('baseGoerli'); - expect(context.network.chainId).toBe(84531); - expect(context.daoFactoryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].baseGoerli.daoFactoryAddress - ); - expect(context.ensRegistryAddress).toBe( - LIVE_CONTRACTS[SupportedVersion.LATEST].baseGoerli.ensRegistryAddress - ); - expect(context.gasFeeEstimationFactor).toBe(0.625); - expect(context.web3Providers.length).toBe(1); - for (const provider of context.web3Providers) { - expect(provider).toBeInstanceOf(JsonRpcProvider); - expect(provider.connection.url).toBe('https://goerli.base.org/'); - const network = provider.network; - expect(network.chainId).toEqual(84531); - expect(network.name).toEqual('baseGoerli'); - expect(network.ensAddress).toEqual( - LIVE_CONTRACTS[SupportedVersion.LATEST].baseGoerli.ensRegistryAddress - ); - } - }); -});