diff --git a/CHEATSHEET.md b/CHEATSHEET.md
new file mode 100644
index 000000000..14db9a2bc
--- /dev/null
+++ b/CHEATSHEET.md
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+Developer Cheatsheet
+
+## Glossary
+
+| Name | Package | Meaning |
+| ------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `OmniPoint` | `utils` | Location of a contract/program in omnichain environment. Consists of an `address` and `EndpointId` |
+| `OmniVector` | `utils` | Directional connection between two `OmniPoint`s. Consists of `from` and `to` `OmniPoint`s |
+| `OmniNode` | `utils` | Combination of an `OmniPoint` and an arbitrary configuration attached to it. Consists of a `point` and `config` |
+| `OmniEdge` | `utils` | Combination of an `OmniVector` and an arbitrary configuration attached to it. Consists of a `vector` and `config` |
+| `OmniGraph` | `utils` | Collection of `OmniNode`s and `OmniEdge`s that together represent a state of an omnichain application. Consists of `contracts` and `connections` |
+| `OmniError` | `utils` | Wraps an arbitrary `error` object to add information about where that error happened. Consists of `error` and `point` |
+| `OmniContract` | `utils-evm` | Wraps an `ethers` `Contract` instance to add information about the endpoint. Consists of `eid` and `contract` |
+| `OmniPointHardhat` | `utils-evm-hardhat` | Hardhat-specific variation of `OmniPoint`. Since in hardhat we can get a contract address by its name (from `deployments`), this version of `OmniPoint` allows us to use `contractName` instead of `address` |
+
+## Conventions
+
+The packages are laid out according to the [principle of least knowledge](https://en.wikipedia.org/wiki/Law_of_Demeter). Their domain of action is also reflected in their name that follows the convention `[DOMAIN-][-MODIFIER]`, for example:
+
+- `utils` package is the most generic package and it itself does not know and cannot use any implementation details of any more specific packages, nor is it specific to any domain
+- `utils-evm` package is specific to the `EVM` implementaion but it is not specific to any domain
+- `ua-utils-evm` package is specific to the `EVM` implementation and specific to the `ua` (user application) domain
+- `ua-utils-evm-hardhat` package is specific to the `EVM` implementation using `hardhat` and specific to the `ua` (user application) domain
+
+The only exceptions to this rule are packages that need to follow an existing naming convention (`create-lz-oapp`) or packages for which the name needs to appeal or be intuitive/familiar to the user (`toolbox-hardhat`)
+
+## Recipes
+
+### `*-hardhat` packages
+
+These packages augment the `hardhat` types and introduce a new property on the `network` configuration: `eid`. This property links the user-defined network names to LayerZero endpoint IDs:
+
+```typescript
+// hardhat.config.ts
+
+const config: HardhatUserConfig = {
+ networks: {
+ "ethereum-mainnet": {
+ eid: EndpointId.ETHEREUM_MAINNET,
+ // ...
+ },
+ },
+};
+```
+
+This property is required for a lot of the tooling to work - the link between network names and endpoints needs to be specified in order to wire OApps successfully.
+
+#### Getting `hre` (`HardhatRuntimeEnvironment`) for a network
+
+```typescript
+// By network name (as specified in hardhat config)
+import { getHreByNetworkName } from "@layerzerolabs/utils-evm-hardhat";
+
+const environment = await getHreByNetworkName("avalanche-testnet");
+
+// By endpoint ID (as specified in hardhat config, using the eid property of a network)
+import { createGetHreByEid } from "@layerzerolabs/utils-evm-hardhat";
+
+// In this case we need to instantiate an environemnt factory
+const getEnvironment = createGetHreByEid();
+
+const eid = EndpointId.AVALANCHE_TESTNET;
+const environment = await getNetworkRuntimeEnvironmentByEid(eid);
+```
+
+#### Getting a contract instance
+
+##### Disconnected, without a provider
+
+```typescript
+// By OmniPointHardhat
+import { createContractFactory } from "@layerzerolabs/utils-evm-hardhat";
+
+// In this case we need to instantiate a contract factory
+const createContract = createContractFactory();
+
+const eid = EndpointId.BST_MAINNET;
+
+// We can ask for the contract by its name and eid
+const contract = await createContract({ eid: address: '0x' })
+
+// Or its name
+const contract = await createContract({ eid: contractName: 'MyOApp' })
+```
+
+##### Connected, with a provider
+
+```typescript
+// By OmniPointHardhat
+import { createConnectedContractFactory } from "@layerzerolabs/utils-evm-hardhat";
+
+// In this case we need to instantiate a contract factory
+const createContract = createConnectedContractFactory();
+
+const eid = EndpointId.BST_MAINNET;
+
+// We can ask for the contract by its name and eid
+const contract = await createContract({ eid: address: '0x' })
+
+// Or its name
+const contract = await createContract({ eid: contractName: 'MyOApp' })
+```
diff --git a/README.md b/README.md
index bafbc4905..aa53c2deb 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,13 @@
LayerZero Contract Utilities
+## Code layout
+
+The code is arranged into:
+
+- **Reusable packages** under `./packages` directory
+- **Example projects** under `./examples` directory
+
## Development
```bash
diff --git a/packages/ua-utils-evm-hardhat-test/test/__utils__/endpoint.ts b/packages/ua-utils-evm-hardhat-test/test/__utils__/endpoint.ts
index 3397e0693..460e3778b 100644
--- a/packages/ua-utils-evm-hardhat-test/test/__utils__/endpoint.ts
+++ b/packages/ua-utils-evm-hardhat-test/test/__utils__/endpoint.ts
@@ -1,6 +1,6 @@
import {
createConnectedContractFactory,
- createNetworkEnvironmentFactory,
+ createGetHreByEid,
createSignerFactory,
OmniGraphBuilderHardhat,
type OmniGraphHardhat,
@@ -65,7 +65,7 @@ export const getDefaultUlnConfig = (dvnAddress: string): Uln302UlnConfig => {
* Deploys an enpoint fixture. Useful for tests
*/
export const deployEndpointFixture = async () => {
- const environmentFactory = createNetworkEnvironmentFactory()
+ const environmentFactory = createGetHreByEid()
const eth = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
const avax = await environmentFactory(EndpointId.AVALANCHE_MAINNET)
@@ -76,7 +76,7 @@ export const deployEndpointFixture = async () => {
* Deploys an enpoint fixture. Useful for when deployment files need to be persisted
*/
export const deployEndpoint = async () => {
- const environmentFactory = createNetworkEnvironmentFactory()
+ const environmentFactory = createGetHreByEid()
const eth = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
const avax = await environmentFactory(EndpointId.AVALANCHE_MAINNET)
diff --git a/packages/ua-utils-evm-hardhat-test/test/__utils__/oapp.ts b/packages/ua-utils-evm-hardhat-test/test/__utils__/oapp.ts
index e2bc1714f..d47ae5464 100644
--- a/packages/ua-utils-evm-hardhat-test/test/__utils__/oapp.ts
+++ b/packages/ua-utils-evm-hardhat-test/test/__utils__/oapp.ts
@@ -1,8 +1,8 @@
import { EndpointId } from '@layerzerolabs/lz-definitions'
-import { createNetworkEnvironmentFactory } from '@layerzerolabs/utils-evm-hardhat'
+import { createGetHreByEid } from '@layerzerolabs/utils-evm-hardhat'
export const deployOApp = async () => {
- const environmentFactory = createNetworkEnvironmentFactory()
+ const environmentFactory = createGetHreByEid()
const eth = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
const avax = await environmentFactory(EndpointId.AVALANCHE_MAINNET)
@@ -13,7 +13,7 @@ export const deployOApp = async () => {
}
export const deployOAppFixture = async () => {
- const environmentFactory = createNetworkEnvironmentFactory()
+ const environmentFactory = createGetHreByEid()
const eth = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
const avax = await environmentFactory(EndpointId.AVALANCHE_MAINNET)
diff --git a/packages/ua-utils-evm-hardhat-test/test/__utils__/omnicounter.ts b/packages/ua-utils-evm-hardhat-test/test/__utils__/omnicounter.ts
index 30389ed7f..044b4f226 100644
--- a/packages/ua-utils-evm-hardhat-test/test/__utils__/omnicounter.ts
+++ b/packages/ua-utils-evm-hardhat-test/test/__utils__/omnicounter.ts
@@ -1,8 +1,8 @@
import { EndpointId } from '@layerzerolabs/lz-definitions'
-import { createNetworkEnvironmentFactory } from '@layerzerolabs/utils-evm-hardhat'
+import { createGetHreByEid } from '@layerzerolabs/utils-evm-hardhat'
export const deployOmniCounter = async () => {
- const environmentFactory = createNetworkEnvironmentFactory()
+ const environmentFactory = createGetHreByEid()
const eth = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
const avax = await environmentFactory(EndpointId.AVALANCHE_MAINNET)
@@ -13,7 +13,7 @@ export const deployOmniCounter = async () => {
}
export const deployOmniCounterFixture = async () => {
- const environmentFactory = createNetworkEnvironmentFactory()
+ const environmentFactory = createGetHreByEid()
const eth = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
const avax = await environmentFactory(EndpointId.AVALANCHE_MAINNET)
diff --git a/packages/utils-evm-hardhat/src/omnigraph/coordinates.ts b/packages/utils-evm-hardhat/src/omnigraph/coordinates.ts
index 69e050ecc..10cd222d3 100644
--- a/packages/utils-evm-hardhat/src/omnigraph/coordinates.ts
+++ b/packages/utils-evm-hardhat/src/omnigraph/coordinates.ts
@@ -4,7 +4,7 @@ import { OmniContract } from '@layerzerolabs/utils-evm'
import { Contract } from '@ethersproject/contracts'
import assert from 'assert'
import { OmniContractFactoryHardhat, OmniDeployment } from './types'
-import { createNetworkEnvironmentFactory } from '@/runtime'
+import { createGetHreByEid } from '@/runtime'
import { assertHardhatDeploy } from '@/internal/assertions'
export const omniDeploymentToPoint = ({ eid, deployment }: OmniDeployment): OmniPoint => ({
@@ -17,9 +17,7 @@ export const omniDeploymentToContract = ({ eid, deployment }: OmniDeployment): O
contract: new Contract(deployment.address, deployment.abi),
})
-export const createContractFactory = (
- environmentFactory = createNetworkEnvironmentFactory()
-): OmniContractFactoryHardhat => {
+export const createContractFactory = (environmentFactory = createGetHreByEid()): OmniContractFactoryHardhat => {
return pMemoize(async ({ eid, address, contractName }) => {
const env = await environmentFactory(eid)
assertHardhatDeploy(env)
diff --git a/packages/utils-evm-hardhat/src/provider.ts b/packages/utils-evm-hardhat/src/provider.ts
index 4d75c0b14..4b2c52c5d 100644
--- a/packages/utils-evm-hardhat/src/provider.ts
+++ b/packages/utils-evm-hardhat/src/provider.ts
@@ -1,12 +1,10 @@
import type { JsonRpcProvider } from '@ethersproject/providers'
import type { ProviderFactory } from '@layerzerolabs/utils-evm'
-import type { HardhatRuntimeEnvironment } from 'hardhat/types'
import pMemoize from 'p-memoize'
-import { createNetworkEnvironmentFactory, getDefaultRuntimeEnvironment, wrapEIP1193Provider } from './runtime'
+import { createGetHreByEid, wrapEIP1193Provider } from './runtime'
export const createProviderFactory = (
- hre: HardhatRuntimeEnvironment = getDefaultRuntimeEnvironment(),
- networkEnvironmentFactory = createNetworkEnvironmentFactory(hre)
+ networkEnvironmentFactory = createGetHreByEid()
): ProviderFactory => {
return pMemoize(async (eid) => {
const env = await networkEnvironmentFactory(eid)
diff --git a/packages/utils-evm-hardhat/src/runtime.ts b/packages/utils-evm-hardhat/src/runtime.ts
index 41fb500ed..edc2d488e 100644
--- a/packages/utils-evm-hardhat/src/runtime.ts
+++ b/packages/utils-evm-hardhat/src/runtime.ts
@@ -6,14 +6,19 @@ import { ConfigurationError } from './errors'
import { HardhatContext } from 'hardhat/internal/context'
import { Environment as HardhatRuntimeEnvironmentImplementation } from 'hardhat/internal/core/runtime-environment'
import { EndpointId } from '@layerzerolabs/lz-definitions'
-import { EndpointBasedFactory, formatEid } from '@layerzerolabs/utils'
+import { EndpointBasedFactory, Factory, formatEid } from '@layerzerolabs/utils'
import { EthersProviderWrapper } from '@nomiclabs/hardhat-ethers/internal/ethers-provider-wrapper'
import assert from 'assert'
/**
* Helper type for when we need to grab something asynchronously by the network name
*/
-export type GetByNetwork = (networkName: string) => Promise
+export type GetByNetwork = Factory<[networkName: string], TValue>
+
+/**
+ * Helper type for when we need to grab something asynchronously by the network name
+ */
+export type GetByEid = Factory<[eid: EndpointId], TValue>
/**
* Returns the default hardhat context for the project, i.e.
@@ -62,7 +67,7 @@ export const getDefaultRuntimeEnvironment = (): HardhatRuntimeEnvironment => {
* Creates a clone of the HardhatRuntimeEnvironment for a particular network
*
* ```typescript
- * const env = getEnvironment("bsc-testnet");
+ * const env = getHreByNetworkName("bsc-testnet");
*
* // All the ususal properties are present
* env.deployments.get("MyContract")
@@ -70,7 +75,7 @@ export const getDefaultRuntimeEnvironment = (): HardhatRuntimeEnvironment => {
*
* @returns {Promise}
*/
-export const getNetworkRuntimeEnvironment: GetByNetwork = pMemoize(async (networkName) => {
+export const getHreByNetworkName: GetByNetwork = pMemoize(async (networkName) => {
const context = getDefaultContext()
const environment = getDefaultRuntimeEnvironment()
@@ -98,6 +103,25 @@ export const getNetworkRuntimeEnvironment: GetByNetwork}
+ */
+export const createGetHreByEid = (
+ hre = getDefaultRuntimeEnvironment()
+): EndpointBasedFactory =>
+ pMemoize(async (eid: EndpointId) => getHreByNetworkName(getNetworkNameForEid(eid, hre)))
+
/**
* Helper function that wraps an EthereumProvider with EthersProviderWrapper
* so that we can use it further with ethers as a regular JsonRpcProvider
@@ -107,26 +131,6 @@ export const getNetworkRuntimeEnvironment: GetByNetwork new EthersProviderWrapper(provider)
-/**
- * Creates a factory function for creating HardhatRuntimeEnvironment
- * based on a hardhat config and an EndpointId
- *
- * ```typescript
- * import hre from "hardhat";
- *
- * const factory = createNetworkEnvironmentFactory(hre);
- * const env = factory(EndpointId.FANTOM_MAINNET)
- * ```
- *
- * @param {HardhatRuntimeEnvironment | undefined} [hre]
- * @returns {(eid: EndpointId) => Promise}
- */
-export const createNetworkEnvironmentFactory = (
- hre: HardhatRuntimeEnvironment = getDefaultRuntimeEnvironment()
-): EndpointBasedFactory => {
- return async (eid) => getNetworkRuntimeEnvironment(getNetworkNameForEid(eid, hre))
-}
-
/**
* Gets an EndpointId defined in the hardhat config
* for a particular network name (as an `eid` property).
diff --git a/packages/utils-evm-hardhat/src/signer/factory.ts b/packages/utils-evm-hardhat/src/signer/factory.ts
index 010a0a159..704738472 100644
--- a/packages/utils-evm-hardhat/src/signer/factory.ts
+++ b/packages/utils-evm-hardhat/src/signer/factory.ts
@@ -1,14 +1,11 @@
-import type { HardhatRuntimeEnvironment } from 'hardhat/types'
import type { OmniSignerFactory } from '@layerzerolabs/utils'
import { OmniSignerEVM } from '@layerzerolabs/utils-evm'
import pMemoize from 'p-memoize'
-import { getDefaultRuntimeEnvironment } from '../runtime'
import { createProviderFactory } from '../provider'
export const createSignerFactory = (
addressOrIndex?: string | number,
- hre: HardhatRuntimeEnvironment = getDefaultRuntimeEnvironment(),
- providerFactory = createProviderFactory(hre)
+ providerFactory = createProviderFactory()
): OmniSignerFactory => {
return pMemoize(async (eid) => {
const provider = await providerFactory(eid)
diff --git a/packages/utils-evm-hardhat/test/omnigraph/coordinates.test.ts b/packages/utils-evm-hardhat/test/omnigraph/coordinates.test.ts
index 82f5ea9ac..4c444d1f7 100644
--- a/packages/utils-evm-hardhat/test/omnigraph/coordinates.test.ts
+++ b/packages/utils-evm-hardhat/test/omnigraph/coordinates.test.ts
@@ -7,7 +7,7 @@ import { OmniDeployment, createContractFactory, omniDeploymentToContract, omniDe
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { Contract } from '@ethersproject/contracts'
import { makeZeroAddress } from '@layerzerolabs/utils-evm'
-import { createNetworkEnvironmentFactory } from '@/runtime'
+import { createGetHreByEid } from '@/runtime'
jest.spyOn(DeploymentsManager.prototype, 'getChainId').mockResolvedValue('1')
@@ -59,7 +59,7 @@ describe('omnigraph/coordinates', () => {
})
it('should resolve when contract has been deployed', async () => {
- const environmentFactory = createNetworkEnvironmentFactory(hre)
+ const environmentFactory = createGetHreByEid(hre)
const contractFactory = createContractFactory(environmentFactory)
const env = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
@@ -110,7 +110,7 @@ describe('omnigraph/coordinates', () => {
it('should resolve when contract has been deployed', async () => {
await fc.assert(
fc.asyncProperty(evmAddressArbitrary, async (address) => {
- const environmentFactory = createNetworkEnvironmentFactory(hre)
+ const environmentFactory = createGetHreByEid(hre)
const contractFactory = createContractFactory(environmentFactory)
const env = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
diff --git a/packages/utils-evm-hardhat/test/provider.test.ts b/packages/utils-evm-hardhat/test/provider.test.ts
index 760babe48..a2a1b0f1e 100644
--- a/packages/utils-evm-hardhat/test/provider.test.ts
+++ b/packages/utils-evm-hardhat/test/provider.test.ts
@@ -1,5 +1,5 @@
-import { getNetworkRuntimeEnvironment } from '@/runtime'
-import hre from 'hardhat'
+import 'hardhat'
+import { createGetHreByEid } from '@/runtime'
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { createProviderFactory } from '@/provider'
import { JsonRpcProvider } from '@ethersproject/providers'
@@ -10,12 +10,17 @@ jest.spyOn(JsonRpcProvider.prototype, 'detectNetwork').mockResolvedValue({ chain
describe('provider', () => {
describe('createProviderFactory', () => {
it('should reject with an endpoint that is not in the hardhat config', async () => {
- await expect(createProviderFactory(hre)(EndpointId.CATHAY_TESTNET)).rejects.toBeTruthy()
+ const environmentFactory = createGetHreByEid()
+ const providerFactory = createProviderFactory(environmentFactory)
+
+ await expect(providerFactory(EndpointId.CATHAY_TESTNET)).rejects.toBeTruthy()
})
- it('should return a Web3Provider wrapping the network provider', async () => {
- const env = await getNetworkRuntimeEnvironment('ethereum-mainnet')
- const provider = await createProviderFactory(hre)(EndpointId.ETHEREUM_MAINNET)
+ it('should return a JsonRpcProvider wrapping the network provider', async () => {
+ const environmentFactory = createGetHreByEid()
+ const providerFactory = createProviderFactory(environmentFactory)
+ const env = await environmentFactory(EndpointId.ETHEREUM_MAINNET)
+ const provider = await providerFactory(EndpointId.ETHEREUM_MAINNET)
expect(provider).toBeInstanceOf(JsonRpcProvider)
diff --git a/packages/utils-evm-hardhat/test/runtime.test.ts b/packages/utils-evm-hardhat/test/runtime.test.ts
index f01d3dadf..86e1f0a91 100644
--- a/packages/utils-evm-hardhat/test/runtime.test.ts
+++ b/packages/utils-evm-hardhat/test/runtime.test.ts
@@ -1,11 +1,6 @@
import hre from 'hardhat'
import { DeploymentsManager } from 'hardhat-deploy/dist/src/DeploymentsManager'
-import {
- createNetworkEnvironmentFactory,
- getEidForNetworkName,
- getNetworkNameForEid,
- getNetworkRuntimeEnvironment,
-} from '@/runtime'
+import { createGetHreByEid, getEidForNetworkName, getNetworkNameForEid, getHreByNetworkName } from '@/runtime'
import type { DeploymentSubmission } from 'hardhat-deploy/dist/types'
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
@@ -13,13 +8,13 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'
jest.spyOn(DeploymentsManager.prototype, 'getChainId').mockResolvedValue('1')
describe('runtime', () => {
- describe('getNetworkRuntimeEnvironment', () => {
+ describe('getHreByNetworkName', () => {
it('should reject with an invalid network', async () => {
- await expect(getNetworkRuntimeEnvironment('not-in-hardhat-config')).rejects.toBeTruthy()
+ await expect(getHreByNetworkName('not-in-hardhat-config')).rejects.toBeTruthy()
})
it('should return a HardhatRuntimeEnvironment with correct network', async () => {
- const runtime = await getNetworkRuntimeEnvironment('ethereum-mainnet')
+ const runtime = await getHreByNetworkName('ethereum-mainnet')
expect(runtime.network.name).toEqual('ethereum-mainnet')
expect(runtime.deployments).toMatchObject({
@@ -28,8 +23,8 @@ describe('runtime', () => {
})
it('should have the config setup correctly', async () => {
- const ethRuntime = await getNetworkRuntimeEnvironment('ethereum-mainnet')
- const bscRuntime = await getNetworkRuntimeEnvironment('bsc-testnet')
+ const ethRuntime = await getHreByNetworkName('ethereum-mainnet')
+ const bscRuntime = await getHreByNetworkName('bsc-testnet')
expect(ethRuntime.network.name).toBe('ethereum-mainnet')
expect(ethRuntime.network.config).toBe(hre.config.networks['ethereum-mainnet'])
@@ -38,8 +33,8 @@ describe('runtime', () => {
})
it('should save the deployment to correct network', async () => {
- const bscRuntime = await getNetworkRuntimeEnvironment('bsc-testnet')
- const ethRuntime = await getNetworkRuntimeEnvironment('ethereum-mainnet')
+ const bscRuntime = await getHreByNetworkName('bsc-testnet')
+ const ethRuntime = await getHreByNetworkName('ethereum-mainnet')
const now = Date.now()
const deploymentSubmission = {
args: ['bsc-testnet', now],
@@ -58,15 +53,15 @@ describe('runtime', () => {
})
})
- describe('createNetworkEnvironmentFactory', () => {
+ describe('createGetHreByEid()', () => {
it('should reject with an endpoint that is not in the hardhat config', async () => {
- await expect(createNetworkEnvironmentFactory(hre)(EndpointId.CATHAY_TESTNET)).rejects.toThrow(
+ await expect(createGetHreByEid(hre)(EndpointId.CATHAY_TESTNET)).rejects.toThrow(
'Could not find a network for eid 10171 (CATHAY_TESTNET)'
)
})
it('should return a HardhatRuntimeEnvironment with correct network', async () => {
- const runtime = await createNetworkEnvironmentFactory(hre)(EndpointId.ETHEREUM_MAINNET)
+ const runtime = await createGetHreByEid(hre)(EndpointId.ETHEREUM_MAINNET)
expect(runtime.network.name).toEqual('ethereum-mainnet')
expect(runtime.deployments).toMatchObject({
diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts
index d2ecad81e..aae0f6e55 100644
--- a/packages/utils/src/types.ts
+++ b/packages/utils/src/types.ts
@@ -21,7 +21,7 @@ export type Bytes32 = string
*/
export type Factory = (...input: TInput) => TOutput | Promise
-export type EndpointBasedFactory = (eid: EndpointId) => TValue | Promise
+export type EndpointBasedFactory = Factory<[eid: EndpointId], TValue>
/**
* Helper type that grabs all the keys of a type / an interface