Update infra package for SDK 1.2.0 (#1836)

- Update infra code to work with update SDK types
- Include some minor cosmetic code improvements
pull/1873/head
J M Rossy 2 years ago committed by GitHub
parent 31a102a0a0
commit e322270477
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      typescript/helloworld
  2. 8
      typescript/infra/config/environments/mainnet2/agent.ts
  3. 38
      typescript/infra/config/environments/mainnet2/chains.ts
  4. 4
      typescript/infra/config/environments/mainnet2/core.ts
  5. 10
      typescript/infra/config/environments/mainnet2/helloworld.ts
  6. 10
      typescript/infra/config/environments/mainnet2/index.ts
  7. 9
      typescript/infra/config/environments/mainnet2/token-bridge.ts
  8. 12
      typescript/infra/config/environments/mainnet2/validators.ts
  9. 4
      typescript/infra/config/environments/test/agent.ts
  10. 10
      typescript/infra/config/environments/test/chains.ts
  11. 4
      typescript/infra/config/environments/test/core.ts
  12. 14
      typescript/infra/config/environments/test/index.ts
  13. 22
      typescript/infra/config/environments/test/liquidityLayer.ts
  14. 4
      typescript/infra/config/environments/test/validators.ts
  15. 8
      typescript/infra/config/environments/testnet3/agent.ts
  16. 22
      typescript/infra/config/environments/testnet3/chains.ts
  17. 4
      typescript/infra/config/environments/testnet3/core.ts
  18. 10
      typescript/infra/config/environments/testnet3/helloworld.ts
  19. 10
      typescript/infra/config/environments/testnet3/index.ts
  20. 22
      typescript/infra/config/environments/testnet3/token-bridge.ts
  21. 28
      typescript/infra/config/environments/testnet3/validators.ts
  22. 16
      typescript/infra/config/utils.ts
  23. 21
      typescript/infra/hardhat.config.ts
  24. 9
      typescript/infra/package.json
  25. 19
      typescript/infra/scripts/announce-validators.ts
  26. 4
      typescript/infra/scripts/check-deploy.ts
  27. 2
      typescript/infra/scripts/core.ts
  28. 20
      typescript/infra/scripts/debug-message.ts
  29. 2
      typescript/infra/scripts/deploy-agents.ts
  30. 16
      typescript/infra/scripts/funding/fund-deterministic-key-from-deployer.ts
  31. 131
      typescript/infra/scripts/funding/fund-keys-from-deployer.ts
  32. 11
      typescript/infra/scripts/funding/reclaim-from-igp.ts
  33. 5
      typescript/infra/scripts/govern.ts
  34. 10
      typescript/infra/scripts/helloworld/deploy.ts
  35. 12
      typescript/infra/scripts/helloworld/kathy.ts
  36. 49
      typescript/infra/scripts/helloworld/utils.ts
  37. 4
      typescript/infra/scripts/list-validator-checkpoint-indices.ts
  38. 6
      typescript/infra/scripts/middleware/circle-relayer.ts
  39. 2
      typescript/infra/scripts/middleware/deploy-accounts.ts
  40. 2
      typescript/infra/scripts/middleware/deploy-liquidity-layer.ts
  41. 2
      typescript/infra/scripts/middleware/deploy-queries.ts
  42. 6
      typescript/infra/scripts/middleware/portal-relayer.ts
  43. 7
      typescript/infra/scripts/output-agent-env-vars.ts
  44. 2
      typescript/infra/scripts/remove-agent-deploys.ts
  45. 3
      typescript/infra/scripts/safe-delegate.ts
  46. 2
      typescript/infra/scripts/update-agents-diff.ts
  47. 28
      typescript/infra/scripts/utils.ts
  48. 4
      typescript/infra/scripts/verify-validators.ts
  49. 4
      typescript/infra/scripts/verify.ts
  50. 2
      typescript/infra/src/agents/aws/key.ts
  51. 8
      typescript/infra/src/agents/aws/user.ts
  52. 8
      typescript/infra/src/agents/aws/validator-user.ts
  53. 41
      typescript/infra/src/agents/index.ts
  54. 30
      typescript/infra/src/agents/key-utils.ts
  55. 50
      typescript/infra/src/config/agent.ts
  56. 19
      typescript/infra/src/config/chain.ts
  57. 14
      typescript/infra/src/config/environment.ts
  58. 10
      typescript/infra/src/config/helloworld.ts
  59. 30
      typescript/infra/src/core/deploy.ts
  60. 55
      typescript/infra/src/core/govern.ts
  61. 40
      typescript/infra/src/core/multisend.ts
  62. 26
      typescript/infra/src/create2/index.ts
  63. 4
      typescript/infra/src/deploy.ts
  64. 12
      typescript/infra/src/funding/deploy-key-funder.ts
  65. 16
      typescript/infra/src/helloworld/kathy.ts
  66. 14
      typescript/infra/src/middleware/liquidity-layer-relayer.ts
  67. 10
      typescript/infra/src/scraper/deploy.ts
  68. 13
      typescript/infra/src/testcontracts/testquerysender.ts
  69. 14
      typescript/infra/src/testcontracts/testrecipient.ts
  70. 19
      typescript/infra/src/utils/safe.ts
  71. 4
      typescript/infra/src/utils/utils.ts
  72. 20
      typescript/infra/test/core.test.ts
  73. 45
      yarn.lock

@ -1 +1 @@
Subproject commit b5087155c1ee3a6c5f9033150668e02481de7383 Subproject commit 75d40a83fda061c37704e7de8bcc3cdbca498b55

@ -9,7 +9,7 @@ import {
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { helloworldMatchingList, routerMatchingList } from '../../utils'; import { helloworldMatchingList, routerMatchingList } from '../../utils';
import { MainnetChains, chainNames, environment } from './chains'; import { chainNames, environment } from './chains';
import { helloWorld } from './helloworld'; import { helloWorld } from './helloworld';
import interchainQueryRouters from './middleware/queries/addresses.json'; import interchainQueryRouters from './middleware/queries/addresses.json';
import { validators } from './validators'; import { validators } from './validators';
@ -23,7 +23,7 @@ const interchainQueriesMatchingList = routerMatchingList(
interchainQueryRouters, interchainQueryRouters,
); );
export const hyperlane: AgentConfig<MainnetChains> = { export const hyperlane: AgentConfig = {
environment, environment,
namespace: environment, namespace: environment,
runEnv: environment, runEnv: environment,
@ -67,7 +67,7 @@ export const hyperlane: AgentConfig<MainnetChains> = {
rolesWithKeys: ALL_KEY_ROLES, rolesWithKeys: ALL_KEY_ROLES,
}; };
export const releaseCandidate: AgentConfig<MainnetChains> = { export const releaseCandidate: AgentConfig = {
environment, environment,
namespace: environment, namespace: environment,
runEnv: environment, runEnv: environment,
@ -98,7 +98,7 @@ export const releaseCandidate: AgentConfig<MainnetChains> = {
transactionGasLimit: BigInt(750000), transactionGasLimit: BigInt(750000),
// Skipping arbitrum because the gas price estimates are inclusive of L1 // Skipping arbitrum because the gas price estimates are inclusive of L1
// fees which leads to wildly off predictions. // fees which leads to wildly off predictions.
skipTransactionGasLimitFor: [chainMetadata.arbitrum.id], skipTransactionGasLimitFor: [chainMetadata.arbitrum.chainId],
}, },
}, },
rolesWithKeys: [KEY_ROLE_ENUM.Relayer, KEY_ROLE_ENUM.Kathy], rolesWithKeys: [KEY_ROLE_ENUM.Relayer, KEY_ROLE_ENUM.Kathy],

@ -1,35 +1,41 @@
import { chainConnectionConfigs } from '@hyperlane-xyz/sdk'; import { ChainMap, ChainMetadata, chainMetadata } from '@hyperlane-xyz/sdk';
export const mainnetConfigs = { export const mainnetConfigs: ChainMap<ChainMetadata> = {
bsc: { bsc: {
...chainConnectionConfigs.bsc, ...chainMetadata.bsc,
overrides: { transactionOverrides: {
gasPrice: 7 * 10 ** 9, // 7 gwei gasPrice: 7 * 10 ** 9, // 7 gwei
}, },
}, },
avalanche: chainConnectionConfigs.avalanche, avalanche: chainMetadata.avalanche,
polygon: { polygon: {
...chainConnectionConfigs.polygon, ...chainMetadata.polygon,
confirmations: 3, blocks: {
overrides: { ...chainMetadata.polygon.blocks,
confirmations: 3,
},
transactionOverrides: {
maxFeePerGas: 500 * 10 ** 9, // 500 gwei maxFeePerGas: 500 * 10 ** 9, // 500 gwei
maxPriorityFeePerGas: 100 * 10 ** 9, // 100 gwei maxPriorityFeePerGas: 100 * 10 ** 9, // 100 gwei
// gasPrice: 50 * 10 ** 9, // 50 gwei // gasPrice: 50 * 10 ** 9, // 50 gwei
}, },
}, },
celo: chainConnectionConfigs.celo, celo: chainMetadata.celo,
arbitrum: chainConnectionConfigs.arbitrum, arbitrum: chainMetadata.arbitrum,
optimism: chainConnectionConfigs.optimism, optimism: chainMetadata.optimism,
ethereum: { ethereum: {
...chainConnectionConfigs.ethereum, ...chainMetadata.ethereum,
confirmations: 3, blocks: {
overrides: { ...chainMetadata.ethereum.blocks,
confirmations: 3,
},
transactionOverrides: {
maxFeePerGas: 150 * 10 ** 9, // gwei maxFeePerGas: 150 * 10 ** 9, // gwei
maxPriorityFeePerGas: 5 * 10 ** 9, // gwei maxPriorityFeePerGas: 5 * 10 ** 9, // gwei
}, },
}, },
moonbeam: chainConnectionConfigs.moonbeam, moonbeam: chainMetadata.moonbeam,
gnosis: chainConnectionConfigs.gnosis, gnosis: chainMetadata.gnosis,
}; };
export type MainnetChains = keyof typeof mainnetConfigs; export type MainnetChains = keyof typeof mainnetConfigs;

@ -1,8 +1,6 @@
import { ChainMap, CoreConfig } from '@hyperlane-xyz/sdk'; import { ChainMap, CoreConfig } from '@hyperlane-xyz/sdk';
import { MainnetChains } from './chains'; export const core: ChainMap<CoreConfig> = {
export const core: ChainMap<MainnetChains, CoreConfig> = {
celo: { celo: {
owner: '0x1DE69322B55AC7E0999F8e7738a1428C8b130E4d', owner: '0x1DE69322B55AC7E0999F8e7738a1428C8b130E4d',
multisigIsm: { multisigIsm: {

@ -3,11 +3,11 @@ import { ConnectionType } from '../../../src/config/agent';
import { HelloWorldKathyRunMode } from '../../../src/config/helloworld'; import { HelloWorldKathyRunMode } from '../../../src/config/helloworld';
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { MainnetChains, environment } from './chains'; import { environment } from './chains';
import hyperlaneAddresses from './helloworld/hyperlane/addresses.json'; import hyperlaneAddresses from './helloworld/hyperlane/addresses.json';
import rcAddresses from './helloworld/rc/addresses.json'; import rcAddresses from './helloworld/rc/addresses.json';
export const hyperlane: HelloWorldConfig<MainnetChains> = { export const hyperlane: HelloWorldConfig = {
addresses: hyperlaneAddresses, addresses: hyperlaneAddresses,
kathy: { kathy: {
docker: { docker: {
@ -28,7 +28,7 @@ export const hyperlane: HelloWorldConfig<MainnetChains> = {
}, },
}; };
export const releaseCandidate: HelloWorldConfig<MainnetChains> = { export const releaseCandidate: HelloWorldConfig = {
addresses: rcAddresses, addresses: rcAddresses,
kathy: { kathy: {
docker: { docker: {
@ -47,9 +47,7 @@ export const releaseCandidate: HelloWorldConfig<MainnetChains> = {
}, },
}; };
export const helloWorld: Partial< export const helloWorld: Partial<Record<Contexts, HelloWorldConfig>> = {
Record<Contexts, HelloWorldConfig<MainnetChains>>
> = {
[Contexts.Hyperlane]: hyperlane, [Contexts.Hyperlane]: hyperlane,
[Contexts.ReleaseCandidate]: releaseCandidate, [Contexts.ReleaseCandidate]: releaseCandidate,
}; };

@ -5,19 +5,15 @@ import { ConnectionType } from '../../../src/config/agent';
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { agents } from './agent'; import { agents } from './agent';
import { import { environment as environmentName, mainnetConfigs } from './chains';
MainnetChains,
environment as environmentName,
mainnetConfigs,
} from './chains';
import { core } from './core'; import { core } from './core';
import { keyFunderConfig } from './funding'; import { keyFunderConfig } from './funding';
import { helloWorld } from './helloworld'; import { helloWorld } from './helloworld';
import { infrastructure } from './infrastructure'; import { infrastructure } from './infrastructure';
export const environment: CoreEnvironmentConfig<MainnetChains> = { export const environment: CoreEnvironmentConfig = {
environment: environmentName, environment: environmentName,
transactionConfigs: mainnetConfigs, chainMetadataConfigs: mainnetConfigs,
getMultiProvider: ( getMultiProvider: (
context: Contexts = Contexts.Hyperlane, context: Contexts = Contexts.Hyperlane,
role: KEY_ROLE_ENUM = KEY_ROLE_ENUM.Deployer, role: KEY_ROLE_ENUM = KEY_ROLE_ENUM.Deployer,

@ -7,15 +7,12 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
const circleDomainMapping = [ const circleDomainMapping = [
{ hyperlaneDomain: chainMetadata[Chains.goerli].id, circleDomain: 0 }, { hyperlaneDomain: chainMetadata[Chains.goerli].chainId, circleDomain: 0 },
{ hyperlaneDomain: chainMetadata[Chains.fuji].id, circleDomain: 1 }, { hyperlaneDomain: chainMetadata[Chains.fuji].chainId, circleDomain: 1 },
]; ];
// Circle deployed contracts // Circle deployed contracts
export const circleBridgeAdapterConfig: ChainMap< export const circleBridgeAdapterConfig: ChainMap<CircleBridgeAdapterConfig> = {
any,
CircleBridgeAdapterConfig
> = {
[Chains.goerli]: { [Chains.goerli]: {
type: BridgeAdapterType.Circle, type: BridgeAdapterType.Circle,
tokenMessengerAddress: '0xdabec94b97f7b5fca28f050cc8eeac2dc9920476', tokenMessengerAddress: '0xdabec94b97f7b5fca28f050cc8eeac2dc9920476',

@ -1,20 +1,18 @@
import { ChainName } from '@hyperlane-xyz/sdk'; import { CoreChainName } from '@hyperlane-xyz/sdk';
import { import {
ChainValidatorConfigs, ChainValidatorConfigs,
CheckpointSyncerType, CheckpointSyncerType,
} from '../../../src/config/agent'; } from '../../../src/config/agent';
import { MainnetChains, environment } from './chains'; import { environment } from './chains';
const s3BucketRegion = 'us-east-1'; const s3BucketRegion = 'us-east-1';
const s3BucketName = <Chain extends ChainName>( const s3BucketName = (chainName: CoreChainName, index: number) =>
chainName: Chain, `hyperlane-${environment}-${chainName}-validator-${index}`;
index: number,
) => `hyperlane-${environment}-${chainName}-validator-${index}`;
export const validators: ChainValidatorConfigs<MainnetChains> = { export const validators: ChainValidatorConfigs = {
celo: { celo: {
interval: 5, interval: 5,
reorgPeriod: 0, reorgPeriod: 0,

@ -6,10 +6,10 @@ import {
} from '../../../src/config/agent'; } from '../../../src/config/agent';
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { TestChains, chainNames } from './chains'; import { chainNames } from './chains';
import { validators } from './validators'; import { validators } from './validators';
export const hyperlane: AgentConfig<TestChains> = { export const hyperlane: AgentConfig = {
environment: 'test', environment: 'test',
namespace: 'test', namespace: 'test',
runEnv: 'test', runEnv: 'test',

@ -1,9 +1,9 @@
import { chainConnectionConfigs } from '@hyperlane-xyz/sdk'; import { ChainMap, ChainMetadata, chainMetadata } from '@hyperlane-xyz/sdk';
export const testConfigs = { export const testConfigs: ChainMap<ChainMetadata> = {
test1: chainConnectionConfigs.test1, test1: chainMetadata.test1,
test2: chainConnectionConfigs.test2, test2: chainMetadata.test2,
test3: chainConnectionConfigs.test3, test3: chainMetadata.test3,
}; };
export type TestChains = keyof typeof testConfigs; export type TestChains = keyof typeof testConfigs;

@ -1,8 +1,6 @@
import { ChainMap, CoreConfig } from '@hyperlane-xyz/sdk'; import { ChainMap, CoreConfig } from '@hyperlane-xyz/sdk';
import { TestChains } from './chains'; export const core: ChainMap<CoreConfig> = {
export const core: ChainMap<TestChains, CoreConfig> = {
// Owner is hardhat account 0 // Owner is hardhat account 0
// Validators are hardhat accounts 1-3 // Validators are hardhat accounts 1-3
test1: { test1: {

@ -1,24 +1,26 @@
import { JsonRpcProvider } from '@ethersproject/providers'; import { JsonRpcProvider } from '@ethersproject/providers';
import { getTestMultiProvider } from '@hyperlane-xyz/sdk'; import { MultiProvider } from '@hyperlane-xyz/sdk';
import { CoreEnvironmentConfig } from '../../../src/config'; import { CoreEnvironmentConfig } from '../../../src/config';
import { agents } from './agent'; import { agents } from './agent';
import { TestChains, testConfigs } from './chains'; import { testConfigs } from './chains';
import { core } from './core'; import { core } from './core';
import { infra } from './infra'; import { infra } from './infra';
export const environment: CoreEnvironmentConfig<TestChains> = { export const environment: CoreEnvironmentConfig = {
environment: 'test', environment: 'test',
transactionConfigs: testConfigs, chainMetadataConfigs: testConfigs,
agents, agents,
core, core,
infra, infra,
// NOTE: Does not work from hardhat.config.ts // NOTE: Does not work from hardhat.config.ts
getMultiProvider: async () => { getMultiProvider: async () => {
const provider = testConfigs.test1.provider! as JsonRpcProvider; const mp = MultiProvider.createTestMultiProvider();
const provider = mp.getProvider('test1') as JsonRpcProvider;
const signer = provider.getSigner(0); const signer = provider.getSigner(0);
return getTestMultiProvider(signer, testConfigs); mp.setSharedSigner(signer);
return mp;
}, },
}; };

@ -7,19 +7,25 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
const circleDomainMapping = [ const circleDomainMapping = [
{ hyperlaneDomain: chainMetadata[Chains.goerli].id, circleDomain: 0 }, { hyperlaneDomain: chainMetadata[Chains.goerli].chainId, circleDomain: 0 },
{ hyperlaneDomain: chainMetadata[Chains.fuji].id, circleDomain: 1 }, { hyperlaneDomain: chainMetadata[Chains.fuji].chainId, circleDomain: 1 },
]; ];
const wormholeDomainMapping = [ const wormholeDomainMapping = [
{ hyperlaneDomain: chainMetadata[Chains.goerli].id, wormholeDomain: 2 }, { hyperlaneDomain: chainMetadata[Chains.goerli].chainId, wormholeDomain: 2 },
{ hyperlaneDomain: chainMetadata[Chains.fuji].id, wormholeDomain: 6 }, { hyperlaneDomain: chainMetadata[Chains.fuji].chainId, wormholeDomain: 6 },
{ hyperlaneDomain: chainMetadata[Chains.mumbai].id, wormholeDomain: 5 }, { hyperlaneDomain: chainMetadata[Chains.mumbai].chainId, wormholeDomain: 5 },
{ hyperlaneDomain: chainMetadata[Chains.bsctestnet].id, wormholeDomain: 4 }, {
{ hyperlaneDomain: chainMetadata[Chains.alfajores].id, wormholeDomain: 14 }, hyperlaneDomain: chainMetadata[Chains.bsctestnet].chainId,
wormholeDomain: 4,
},
{
hyperlaneDomain: chainMetadata[Chains.alfajores].chainId,
wormholeDomain: 14,
},
]; ];
export const bridgeAdapterConfigs: ChainMap<any, BridgeAdapterConfig> = { export const bridgeAdapterConfigs: ChainMap<BridgeAdapterConfig> = {
[Chains.goerli]: { [Chains.goerli]: {
portal: { portal: {
type: BridgeAdapterType.Portal, type: BridgeAdapterType.Portal,

@ -5,12 +5,10 @@ import {
CheckpointSyncerType, CheckpointSyncerType,
} from '../../../src/config/agent'; } from '../../../src/config/agent';
import { TestChains } from './chains';
const localStoragePath = (chainName: ChainName) => const localStoragePath = (chainName: ChainName) =>
`/tmp/hyperlane-test-${chainName}-validator`; `/tmp/hyperlane-test-${chainName}-validator`;
export const validators: ChainValidatorConfigs<TestChains> = { export const validators: ChainValidatorConfigs = {
test1: { test1: {
interval: 5, interval: 5,
reorgPeriod: 0, reorgPeriod: 0,

@ -9,7 +9,7 @@ import {
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { helloworldMatchingList, routerMatchingList } from '../../utils'; import { helloworldMatchingList, routerMatchingList } from '../../utils';
import { TestnetChains, chainNames, environment } from './chains'; import { chainNames, environment } from './chains';
import { helloWorld } from './helloworld'; import { helloWorld } from './helloworld';
import interchainQueryRouters from './middleware/queries/addresses.json'; import interchainQueryRouters from './middleware/queries/addresses.json';
import { validators } from './validators'; import { validators } from './validators';
@ -23,7 +23,7 @@ const interchainQueriesMatchingList = routerMatchingList(
interchainQueryRouters, interchainQueryRouters,
); );
export const hyperlane: AgentConfig<TestnetChains> = { export const hyperlane: AgentConfig = {
environment, environment,
namespace: environment, namespace: environment,
runEnv: environment, runEnv: environment,
@ -64,7 +64,7 @@ export const hyperlane: AgentConfig<TestnetChains> = {
rolesWithKeys: ALL_KEY_ROLES, rolesWithKeys: ALL_KEY_ROLES,
}; };
export const releaseCandidate: AgentConfig<TestnetChains> = { export const releaseCandidate: AgentConfig = {
environment, environment,
namespace: environment, namespace: environment,
runEnv: environment, runEnv: environment,
@ -95,7 +95,7 @@ export const releaseCandidate: AgentConfig<TestnetChains> = {
transactionGasLimit: BigInt(750000), transactionGasLimit: BigInt(750000),
// Skipping arbitrum because the gas price estimates are inclusive of L1 // Skipping arbitrum because the gas price estimates are inclusive of L1
// fees which leads to wildly off predictions. // fees which leads to wildly off predictions.
skipTransactionGasLimitFor: [chainMetadata.arbitrumgoerli.id], skipTransactionGasLimitFor: [chainMetadata.arbitrumgoerli.chainId],
}, },
}, },
rolesWithKeys: [KEY_ROLE_ENUM.Relayer, KEY_ROLE_ENUM.Kathy], rolesWithKeys: [KEY_ROLE_ENUM.Relayer, KEY_ROLE_ENUM.Kathy],

@ -1,20 +1,20 @@
import { chainConnectionConfigs } from '@hyperlane-xyz/sdk'; import { ChainMap, ChainMetadata, chainMetadata } from '@hyperlane-xyz/sdk';
export const testnetConfigs = { export const testnetConfigs: ChainMap<ChainMetadata> = {
alfajores: chainConnectionConfigs.alfajores, alfajores: chainMetadata.alfajores,
fuji: chainConnectionConfigs.fuji, fuji: chainMetadata.fuji,
mumbai: { mumbai: {
...chainConnectionConfigs.mumbai, ...chainMetadata.mumbai,
overrides: { transactionOverrides: {
maxFeePerGas: 70 * 10 ** 9, // 70 gwei maxFeePerGas: 70 * 10 ** 9, // 70 gwei
maxPriorityFeePerGas: 40 * 10 ** 9, // 40 gwei maxPriorityFeePerGas: 40 * 10 ** 9, // 40 gwei
}, },
}, },
bsctestnet: chainConnectionConfigs.bsctestnet, bsctestnet: chainMetadata.bsctestnet,
goerli: chainConnectionConfigs.goerli, goerli: chainMetadata.goerli,
moonbasealpha: chainConnectionConfigs.moonbasealpha, moonbasealpha: chainMetadata.moonbasealpha,
optimismgoerli: chainConnectionConfigs.optimismgoerli, optimismgoerli: chainMetadata.optimismgoerli,
arbitrumgoerli: chainConnectionConfigs.arbitrumgoerli, arbitrumgoerli: chainMetadata.arbitrumgoerli,
}; };
export type TestnetChains = keyof typeof testnetConfigs; export type TestnetChains = keyof typeof testnetConfigs;

@ -1,8 +1,6 @@
import { ChainMap, CoreConfig } from '@hyperlane-xyz/sdk'; import { ChainMap, CoreConfig } from '@hyperlane-xyz/sdk';
import { TestnetChains } from './chains'; export const core: ChainMap<CoreConfig> = {
export const core: ChainMap<TestnetChains, CoreConfig> = {
alfajores: { alfajores: {
owner: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C', owner: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C',
multisigIsm: { multisigIsm: {

@ -3,11 +3,11 @@ import { ConnectionType } from '../../../src/config/agent';
import { HelloWorldKathyRunMode } from '../../../src/config/helloworld'; import { HelloWorldKathyRunMode } from '../../../src/config/helloworld';
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { TestnetChains, environment } from './chains'; import { environment } from './chains';
import hyperlaneAddresses from './helloworld/hyperlane/addresses.json'; import hyperlaneAddresses from './helloworld/hyperlane/addresses.json';
import rcAddresses from './helloworld/rc/addresses.json'; import rcAddresses from './helloworld/rc/addresses.json';
export const hyperlane: HelloWorldConfig<TestnetChains> = { export const hyperlane: HelloWorldConfig = {
addresses: hyperlaneAddresses, addresses: hyperlaneAddresses,
kathy: { kathy: {
docker: { docker: {
@ -27,7 +27,7 @@ export const hyperlane: HelloWorldConfig<TestnetChains> = {
}, },
}; };
export const releaseCandidate: HelloWorldConfig<TestnetChains> = { export const releaseCandidate: HelloWorldConfig = {
addresses: rcAddresses, addresses: rcAddresses,
kathy: { kathy: {
docker: { docker: {
@ -46,9 +46,7 @@ export const releaseCandidate: HelloWorldConfig<TestnetChains> = {
}, },
}; };
export const helloWorld: Partial< export const helloWorld: Partial<Record<Contexts, HelloWorldConfig>> = {
Record<Contexts, HelloWorldConfig<TestnetChains>>
> = {
[Contexts.Hyperlane]: hyperlane, [Contexts.Hyperlane]: hyperlane,
[Contexts.ReleaseCandidate]: releaseCandidate, [Contexts.ReleaseCandidate]: releaseCandidate,
}; };

@ -5,20 +5,16 @@ import { ConnectionType } from '../../../src/config/agent';
import { Contexts } from '../../contexts'; import { Contexts } from '../../contexts';
import { agents } from './agent'; import { agents } from './agent';
import { import { environment as environmentName, testnetConfigs } from './chains';
TestnetChains,
environment as environmentName,
testnetConfigs,
} from './chains';
import { core } from './core'; import { core } from './core';
import { keyFunderConfig } from './funding'; import { keyFunderConfig } from './funding';
import { helloWorld } from './helloworld'; import { helloWorld } from './helloworld';
import { infrastructure } from './infrastructure'; import { infrastructure } from './infrastructure';
import { liquidityLayerRelayerConfig } from './middleware'; import { liquidityLayerRelayerConfig } from './middleware';
export const environment: CoreEnvironmentConfig<TestnetChains> = { export const environment: CoreEnvironmentConfig = {
environment: environmentName, environment: environmentName,
transactionConfigs: testnetConfigs, chainMetadataConfigs: testnetConfigs,
getMultiProvider: ( getMultiProvider: (
context: Contexts = Contexts.Hyperlane, context: Contexts = Contexts.Hyperlane,
role: KEY_ROLE_ENUM = KEY_ROLE_ENUM.Deployer, role: KEY_ROLE_ENUM = KEY_ROLE_ENUM.Deployer,

@ -7,19 +7,25 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
const circleDomainMapping = [ const circleDomainMapping = [
{ hyperlaneDomain: chainMetadata[Chains.goerli].id, circleDomain: 0 }, { hyperlaneDomain: chainMetadata[Chains.goerli].chainId, circleDomain: 0 },
{ hyperlaneDomain: chainMetadata[Chains.fuji].id, circleDomain: 1 }, { hyperlaneDomain: chainMetadata[Chains.fuji].chainId, circleDomain: 1 },
]; ];
const wormholeDomainMapping = [ const wormholeDomainMapping = [
{ hyperlaneDomain: chainMetadata[Chains.goerli].id, wormholeDomain: 2 }, { hyperlaneDomain: chainMetadata[Chains.goerli].chainId, wormholeDomain: 2 },
{ hyperlaneDomain: chainMetadata[Chains.fuji].id, wormholeDomain: 6 }, { hyperlaneDomain: chainMetadata[Chains.fuji].chainId, wormholeDomain: 6 },
{ hyperlaneDomain: chainMetadata[Chains.mumbai].id, wormholeDomain: 5 }, { hyperlaneDomain: chainMetadata[Chains.mumbai].chainId, wormholeDomain: 5 },
{ hyperlaneDomain: chainMetadata[Chains.bsctestnet].id, wormholeDomain: 4 }, {
{ hyperlaneDomain: chainMetadata[Chains.alfajores].id, wormholeDomain: 14 }, hyperlaneDomain: chainMetadata[Chains.bsctestnet].chainId,
wormholeDomain: 4,
},
{
hyperlaneDomain: chainMetadata[Chains.alfajores].chainId,
wormholeDomain: 14,
},
]; ];
export const bridgeAdapterConfigs: ChainMap<any, BridgeAdapterConfig> = { export const bridgeAdapterConfigs: ChainMap<BridgeAdapterConfig> = {
[Chains.goerli]: { [Chains.goerli]: {
portal: { portal: {
type: BridgeAdapterType.Portal, type: BridgeAdapterType.Portal,

@ -1,23 +1,21 @@
import { ChainName, chainMetadata } from '@hyperlane-xyz/sdk'; import { CoreChainName, chainMetadata } from '@hyperlane-xyz/sdk';
import { import {
ChainValidatorConfigs, ChainValidatorConfigs,
CheckpointSyncerType, CheckpointSyncerType,
} from '../../../src/config/agent'; } from '../../../src/config/agent';
import { TestnetChains, environment } from './chains'; import { environment } from './chains';
const s3BucketRegion = 'us-east-1'; const s3BucketRegion = 'us-east-1';
const s3BucketName = <Chain extends ChainName>( const s3BucketName = (chainName: CoreChainName, index: number) =>
chainName: Chain, `hyperlane-${environment}-${chainName}-validator-${index}`;
index: number,
) => `hyperlane-${environment}-${chainName}-validator-${index}`;
export const validators: ChainValidatorConfigs<TestnetChains> = { export const validators: ChainValidatorConfigs = {
alfajores: { alfajores: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.alfajores.blocks.reorgPeriod, reorgPeriod: chainMetadata.alfajores.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0xe6072396568e73ce6803b12b7e04164e839f1e54', address: '0xe6072396568e73ce6803b12b7e04164e839f1e54',
@ -50,7 +48,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
fuji: { fuji: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.fuji.blocks.reorgPeriod, reorgPeriod: chainMetadata.fuji.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0x9fa19ead5ec76e437948b35e227511b106293c40', address: '0x9fa19ead5ec76e437948b35e227511b106293c40',
@ -83,7 +81,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
mumbai: { mumbai: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.mumbai.blocks.reorgPeriod, reorgPeriod: chainMetadata.mumbai.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0x0a664ea799447da6b15645cf8b9e82072a68343f', address: '0x0a664ea799447da6b15645cf8b9e82072a68343f',
@ -116,7 +114,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
bsctestnet: { bsctestnet: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.bsctestnet.blocks.reorgPeriod, reorgPeriod: chainMetadata.bsctestnet.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0x23338c8714976dd4a57eaeff17cbd26d7e275c08', address: '0x23338c8714976dd4a57eaeff17cbd26d7e275c08',
@ -149,7 +147,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
goerli: { goerli: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.goerli.blocks.reorgPeriod, reorgPeriod: chainMetadata.goerli.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0xf43fbd072fd38e1121d4b3b0b8a35116bbb01ea9', address: '0xf43fbd072fd38e1121d4b3b0b8a35116bbb01ea9',
@ -182,7 +180,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
moonbasealpha: { moonbasealpha: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.moonbasealpha.blocks.reorgPeriod, reorgPeriod: chainMetadata.moonbasealpha.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0x890c2aeac157c3f067f3e42b8afc797939c59a32', address: '0x890c2aeac157c3f067f3e42b8afc797939c59a32',
@ -215,7 +213,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
optimismgoerli: { optimismgoerli: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.optimismgoerli.blocks.reorgPeriod, reorgPeriod: chainMetadata.optimismgoerli.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0xbb8d77eefbecc55db6e5a19b0fc3dc290776f189', address: '0xbb8d77eefbecc55db6e5a19b0fc3dc290776f189',
@ -248,7 +246,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
}, },
arbitrumgoerli: { arbitrumgoerli: {
interval: 5, interval: 5,
reorgPeriod: chainMetadata.arbitrumgoerli.blocks.reorgPeriod, reorgPeriod: chainMetadata.arbitrumgoerli.blocks!.reorgPeriod!,
validators: [ validators: [
{ {
address: '0xce798fa21e323f6b24d9838a10ffecdefdfc4f30', address: '0xce798fa21e323f6b24d9838a10ffecdefdfc4f30',

@ -1,4 +1,4 @@
import { ChainMap, ChainName, chainMetadata } from '@hyperlane-xyz/sdk'; import { ChainMap, chainMetadata } from '@hyperlane-xyz/sdk';
import { HelloWorldConfig } from '../src/config'; import { HelloWorldConfig } from '../src/config';
import { MatchingList } from '../src/config/agent'; import { MatchingList } from '../src/config/agent';
@ -14,8 +14,8 @@ export const MATCHING_LIST_ALL_WILDCARDS = [
}, },
]; ];
export function helloworldMatchingList<Chain extends ChainName>( export function helloworldMatchingList(
helloWorldConfigs: Partial<Record<Contexts, HelloWorldConfig<Chain>>>, helloWorldConfigs: Partial<Record<Contexts, HelloWorldConfig>>,
context: Contexts, context: Contexts,
) { ) {
const helloWorldConfig = helloWorldConfigs[context]; const helloWorldConfig = helloWorldConfigs[context];
@ -25,10 +25,8 @@ export function helloworldMatchingList<Chain extends ChainName>(
return routerMatchingList(helloWorldConfig.addresses); return routerMatchingList(helloWorldConfig.addresses);
} }
export function routerMatchingList<Chain extends ChainName>( export function routerMatchingList(routers: ChainMap<{ router: string }>) {
routers: ChainMap<Chain, { router: string }>, const chains = Object.keys(routers);
) {
const chains = Object.keys(routers) as Chain[];
const matchingList: MatchingList = []; const matchingList: MatchingList = [];
@ -39,9 +37,9 @@ export function routerMatchingList<Chain extends ChainName>(
} }
matchingList.push({ matchingList.push({
originDomain: chainMetadata[source].id, originDomain: chainMetadata[source].chainId,
senderAddress: routers[source].router, senderAddress: routers[source].router,
destinationDomain: chainMetadata[destination].id, destinationDomain: chainMetadata[destination].chainId,
recipientAddress: routers[destination].router, recipientAddress: routers[destination].router,
}); });
} }

@ -4,20 +4,11 @@ import { task } from 'hardhat/config';
import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { TestSendReceiver__factory } from '@hyperlane-xyz/core'; import { TestSendReceiver__factory } from '@hyperlane-xyz/core';
import { import { ChainName, HyperlaneCore, MultiProvider } from '@hyperlane-xyz/sdk';
ChainName,
ChainNameToDomainId,
HyperlaneCore,
getTestMultiProvider,
} from '@hyperlane-xyz/sdk';
import { getCoreEnvironmentConfig } from './scripts/utils';
import { sleep } from './src/utils/utils'; import { sleep } from './src/utils/utils';
const chainSummary = async <Chain extends ChainName>( const chainSummary = async (core: HyperlaneCore, chain: ChainName) => {
core: HyperlaneCore<Chain>,
chain: Chain,
) => {
const coreContracts = core.getContracts(chain); const coreContracts = core.getContracts(chain);
const mailbox = coreContracts.mailbox.contract; const mailbox = coreContracts.mailbox.contract;
const dispatched = await mailbox.count(); const dispatched = await mailbox.count();
@ -50,12 +41,8 @@ task('kathy', 'Dispatches random hyperlane messages')
const timeout = Number.parseInt(taskArgs.timeout); const timeout = Number.parseInt(taskArgs.timeout);
const environment = 'test'; const environment = 'test';
const interchainGasPayment = hre.ethers.utils.parseUnits('100', 'gwei'); const interchainGasPayment = hre.ethers.utils.parseUnits('100', 'gwei');
const config = getCoreEnvironmentConfig(environment);
const [signer] = await hre.ethers.getSigners(); const [signer] = await hre.ethers.getSigners();
const multiProvider = getTestMultiProvider( const multiProvider = MultiProvider.createTestMultiProvider({ signer });
signer,
config.transactionConfigs,
);
const core = HyperlaneCore.fromEnvironment(environment, multiProvider); const core = HyperlaneCore.fromEnvironment(environment, multiProvider);
const randomElement = <T>(list: T[]) => const randomElement = <T>(list: T[]) =>
@ -72,7 +59,7 @@ task('kathy', 'Dispatches random hyperlane messages')
while (run_forever || rounds-- > 0) { while (run_forever || rounds-- > 0) {
const local = core.chains()[0]; const local = core.chains()[0];
const remote: ChainName = randomElement(core.remoteChains(local)); const remote: ChainName = randomElement(core.remoteChains(local));
const remoteId = ChainNameToDomainId[remote]; const remoteId = multiProvider.getDomainId(remote);
const coreContracts = core.getContracts(local); const coreContracts = core.getContracts(local);
const mailbox = coreContracts.mailbox.contract; const mailbox = coreContracts.mailbox.contract;
const paymaster = coreContracts.interchainGasPaymaster; const paymaster = coreContracts.interchainGasPaymaster;

@ -1,7 +1,7 @@
{ {
"name": "@hyperlane-xyz/infra", "name": "@hyperlane-xyz/infra",
"description": "Infrastructure utilities for the Hyperlane Network", "description": "Infrastructure utilities for the Hyperlane Network",
"version": "1.1.4", "version": "1.2.0",
"dependencies": { "dependencies": {
"@arbitrum/sdk": "^3.0.0", "@arbitrum/sdk": "^3.0.0",
"@aws-sdk/client-iam": "^3.74.0", "@aws-sdk/client-iam": "^3.74.0",
@ -14,10 +14,9 @@
"@gnosis.pm/safe-core-sdk": "^2.3.2", "@gnosis.pm/safe-core-sdk": "^2.3.2",
"@gnosis.pm/safe-ethers-lib": "^1.4.0", "@gnosis.pm/safe-ethers-lib": "^1.4.0",
"@gnosis.pm/safe-service-client": "^1.2.0", "@gnosis.pm/safe-service-client": "^1.2.0",
"@hyperlane-xyz/celo-ethers-provider": "^0.1.1", "@hyperlane-xyz/helloworld": "1.2.0",
"@hyperlane-xyz/helloworld": "1.1.4", "@hyperlane-xyz/sdk": "1.2.0",
"@hyperlane-xyz/sdk": "1.1.4", "@hyperlane-xyz/utils": "1.2.0",
"@hyperlane-xyz/utils": "1.1.4",
"@nomiclabs/hardhat-etherscan": "^3.0.3", "@nomiclabs/hardhat-etherscan": "^3.0.3",
"@safe-global/safe-core-sdk": "3.2.0", "@safe-global/safe-core-sdk": "3.2.0",
"@safe-global/safe-ethers-lib": "^1.7.0", "@safe-global/safe-ethers-lib": "^1.7.0",

@ -4,11 +4,7 @@ import { readFileSync } from 'fs';
import * as path from 'path'; import * as path from 'path';
import yargs from 'yargs'; import yargs from 'yargs';
import { import { AllChains, ChainName, HyperlaneCore } from '@hyperlane-xyz/sdk';
AllChains,
ChainNameToDomainId,
HyperlaneCore,
} from '@hyperlane-xyz/sdk';
import { S3Validator } from '../src/agents/aws/validator'; import { S3Validator } from '../src/agents/aws/validator';
import { CheckpointSyncerType } from '../src/config/agent'; import { CheckpointSyncerType } from '../src/config/agent';
@ -54,13 +50,13 @@ async function main() {
// environments union doesn't work well with typescript // environments union doesn't work well with typescript
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const announcements = []; const announcements = [];
const chains = []; const chains: ChainName[] = [];
if (location) { if (location) {
chains.push(chain); chains.push(chain!);
if (location.startsWith('s3://')) { if (location.startsWith('s3://')) {
const validator = await S3Validator.fromStorageLocation(location); const validator = await S3Validator.fromStorageLocation(location);
announcements.push(await validator.getAnnouncement()); announcements.push(await validator.getAnnouncement());
@ -89,9 +85,8 @@ async function main() {
validatorBaseConfig.checkpointSyncer.type == validatorBaseConfig.checkpointSyncer.type ==
CheckpointSyncerType.S3 CheckpointSyncerType.S3
) { ) {
// @ts-ignore
const contracts = core.getContracts(chain); const contracts = core.getContracts(chain);
const localDomain = ChainNameToDomainId[chain]; const localDomain = multiProvider.getDomainId(chain);
const validator = new S3Validator( const validator = new S3Validator(
validatorBaseConfig.address, validatorBaseConfig.address,
localDomain, localDomain,
@ -111,7 +106,6 @@ async function main() {
for (let i = 0; i < announcements.length; i++) { for (let i = 0; i < announcements.length; i++) {
const announcement = announcements[i]; const announcement = announcements[i];
const chain = chains[i]; const chain = chains[i];
// @ts-ignore why?
const contracts = core.getContracts(chain); const contracts = core.getContracts(chain);
const validatorAnnounce = contracts.validatorAnnounce; const validatorAnnounce = contracts.validatorAnnounce;
const address = announcement.value.validator; const address = announcement.value.validator;
@ -123,12 +117,11 @@ async function main() {
if (!announced) { if (!announced) {
const signature = ethers.utils.joinSignature(announcement.signature); const signature = ethers.utils.joinSignature(announcement.signature);
console.log(`Announcing ${address} checkpoints at ${location}`); console.log(`Announcing ${address} checkpoints at ${location}`);
const chainConnection = multiProvider.tryGetChainConnection(chain);
await validatorAnnounce.announce( await validatorAnnounce.announce(
address, address,
location, location,
signature, signature,
chainConnection?.overrides, multiProvider.getTransactionOverrides(chain),
); );
} else { } else {
console.log(`Already announced ${address} checkpoints at ${location}`); console.log(`Already announced ${address} checkpoints at ${location}`);

@ -12,9 +12,9 @@ async function check() {
// environments union doesn't work well with typescript // environments union doesn't work well with typescript
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const coreChecker = new HyperlaneCoreChecker<any>( const coreChecker = new HyperlaneCoreChecker(
multiProvider, multiProvider,
core, core,
config.core, config.core,

@ -18,7 +18,7 @@ import {
async function main() { async function main() {
const environment = await getEnvironment(); const environment = await getEnvironment();
const config = getCoreEnvironmentConfig(environment) as any; const config = getCoreEnvironmentConfig(environment);
const multiProvider = await config.getMultiProvider(); const multiProvider = await config.getMultiProvider();
const deployer = new HyperlaneCoreInfraDeployer( const deployer = new HyperlaneCoreInfraDeployer(
multiProvider, multiProvider,

@ -2,10 +2,8 @@ import { IMessageRecipient__factory } from '@hyperlane-xyz/helloworld/dist/src/t
import { import {
ChainName, ChainName,
DispatchedMessage, DispatchedMessage,
DomainIdToChainName,
HyperlaneCore, HyperlaneCore,
MultiProvider, MultiProvider,
chainConnectionConfigs,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { utils } from '@hyperlane-xyz/utils'; import { utils } from '@hyperlane-xyz/utils';
@ -41,14 +39,14 @@ async function main() {
// Intentionally use public RPC providers to avoid requiring access to our GCP secrets // Intentionally use public RPC providers to avoid requiring access to our GCP secrets
// to run this script // to run this script
const multiProvider = new MultiProvider(chainConnectionConfigs); const multiProvider = new MultiProvider();
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider, multiProvider,
); );
const originProvider = multiProvider.getChainProvider(argv.originChain); const originProvider = multiProvider.getProvider(argv.originChain);
const dispatchReceipt = await originProvider.getTransactionReceipt( const dispatchReceipt = await originProvider.getTransactionReceipt(
argv.txHash, argv.txHash,
); );
@ -66,8 +64,8 @@ async function main() {
} }
async function checkMessage( async function checkMessage(
core: HyperlaneCore<any>, core: HyperlaneCore,
multiProvider: MultiProvider<any>, multiProvider: MultiProvider,
message: DispatchedMessage, message: DispatchedMessage,
) { ) {
const messageId = utils.messageId(message.message); const messageId = utils.messageId(message.message);
@ -75,7 +73,9 @@ async function checkMessage(
console.log(`Raw bytes: ${message.message}`); console.log(`Raw bytes: ${message.message}`);
console.log('Parsed message:', message.parsed); console.log('Parsed message:', message.parsed);
const destinationChain = DomainIdToChainName[message.parsed.destination]; const destinationChain = multiProvider.getChainName(
message.parsed.destination,
);
if (destinationChain === undefined) { if (destinationChain === undefined) {
console.error( console.error(
@ -120,7 +120,7 @@ async function checkMessage(
return; return;
} }
const destinationProvider = multiProvider.getChainProvider(destinationChain); const destinationProvider = multiProvider.getProvider(destinationChain);
const recipient = IMessageRecipient__factory.connect( const recipient = IMessageRecipient__factory.connect(
recipientAddress, recipientAddress,
destinationProvider, destinationProvider,
@ -159,11 +159,11 @@ async function checkMessage(
} }
async function isContract( async function isContract(
multiProvider: MultiProvider<any>, multiProvider: MultiProvider,
chain: ChainName, chain: ChainName,
address: string, address: string,
) { ) {
const provider = multiProvider.getChainProvider(chain); const provider = multiProvider.getProvider(chain);
const code = await provider.getCode(address); const code = await provider.getCode(address);
// "Empty" code // "Empty" code
return code !== '0x'; return code !== '0x';

@ -24,7 +24,7 @@ async function deploy() {
// While this function still has these side effects, the workaround is to just // While this function still has these side effects, the workaround is to just
// run the create-keys script first. // run the create-keys script first.
await Promise.all( await Promise.all(
agentConfig.contextChainNames.map((name: any) => agentConfig.contextChainNames.map((name: string) =>
runAgentHelmCommand(HelmCommand.InstallOrUpgrade, agentConfig, name), runAgentHelmCommand(HelmCommand.InstallOrUpgrade, agentConfig, name),
), ),
); );

@ -1,7 +1,7 @@
import { BigNumber } from 'ethers'; import { BigNumber } from 'ethers';
import { format } from 'util'; import { format } from 'util';
import { objMap, promiseObjAll } from '@hyperlane-xyz/sdk'; import { promiseObjAll } from '@hyperlane-xyz/sdk';
import { error } from '@hyperlane-xyz/utils'; import { error } from '@hyperlane-xyz/utils';
import { Contexts } from '../../config/contexts'; import { Contexts } from '../../config/contexts';
@ -59,16 +59,18 @@ async function main() {
).address; ).address;
await promiseObjAll( await promiseObjAll(
objMap(multiProvider.chainMap, async (chain, dc) => { multiProvider.mapKnownChains(async (chain) => {
if (argv.chainsToSkip?.includes(chain)) { if (argv.chainsToSkip?.includes(chain)) {
return; return;
} }
// fund signer on each network with gas * gasPrice // fund signer on each network with gas * gasPrice
const actual = await dc.provider.getBalance(address); const provider = multiProvider.getProvider(chain);
const overrides = multiProvider.getTransactionOverrides(chain);
const actual = await provider.getBalance(address);
const gasPrice = BigNumber.from( const gasPrice = BigNumber.from(
await (dc.overrides.gasPrice || await (overrides.gasPrice ||
dc.overrides.maxFeePerGas || overrides.maxFeePerGas ||
dc.provider.getGasPrice()), provider.getGasPrice()),
); );
const desired = gasPrice.mul(argv.gasAmount!); const desired = gasPrice.mul(argv.gasAmount!);
const value = desired.sub(actual); const value = desired.sub(actual);
@ -76,7 +78,7 @@ async function main() {
console.log( console.log(
`Funding ${address} on chain '${chain}' with ${value} native tokens`, `Funding ${address} on chain '${chain}' with ${value} native tokens`,
); );
await dc.sendTransaction({ await multiProvider.sendTransaction(chain, {
to: address, to: address,
value, value,
}); });

@ -5,11 +5,9 @@ import { format } from 'util';
import { import {
AllChains, AllChains,
ChainConnection,
ChainName, ChainName,
ChainNameToDomainId,
Chains, Chains,
CompleteChainMap, CoreChainName,
MultiProvider, MultiProvider,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { ChainMap } from '@hyperlane-xyz/sdk/dist/types'; import { ChainMap } from '@hyperlane-xyz/sdk/dist/types';
@ -51,7 +49,7 @@ const L2Chains: ChainName[] = [
Chains.arbitrumgoerli, Chains.arbitrumgoerli,
]; ];
const L2ToL1: ChainMap<L2Chain, ChainName> = { const L2ToL1: ChainMap<ChainName> = {
optimismgoerli: 'goerli', optimismgoerli: 'goerli',
arbitrumgoerli: 'goerli', arbitrumgoerli: 'goerli',
optimism: 'ethereum', optimism: 'ethereum',
@ -94,7 +92,7 @@ const MIN_DELTA_DENOMINATOR = ethers.BigNumber.from(10);
const RC_FUNDING_DISCOUNT_NUMERATOR = ethers.BigNumber.from(2); const RC_FUNDING_DISCOUNT_NUMERATOR = ethers.BigNumber.from(2);
const RC_FUNDING_DISCOUNT_DENOMINATOR = ethers.BigNumber.from(10); const RC_FUNDING_DISCOUNT_DENOMINATOR = ethers.BigNumber.from(10);
const desiredBalancePerChain: CompleteChainMap<string> = { const desiredBalancePerChain: ChainMap<string> = {
celo: '0.3', celo: '0.3',
alfajores: '1', alfajores: '1',
avalanche: '0.3', avalanche: '0.3',
@ -211,7 +209,7 @@ class ContextFunder {
public readonly chains: ChainName[]; public readonly chains: ChainName[];
constructor( constructor(
public readonly multiProvider: MultiProvider<any>, public readonly multiProvider: MultiProvider,
public readonly keys: BaseCloudAgentKey[], public readonly keys: BaseCloudAgentKey[],
public readonly context: Contexts, public readonly context: Contexts,
public readonly rolesToFund: KEY_ROLE_ENUM[], public readonly rolesToFund: KEY_ROLE_ENUM[],
@ -224,7 +222,7 @@ class ContextFunder {
} }
static fromSerializedAddressFile( static fromSerializedAddressFile(
multiProvider: MultiProvider<any>, multiProvider: MultiProvider,
path: string, path: string,
contextsAndRolesToFund: ContextAndRolesMap, contextsAndRolesToFund: ContextAndRolesMap,
) { ) {
@ -240,7 +238,7 @@ class ContextFunder {
// references newer chains. // references newer chains.
return ( return (
parsed.chainName === undefined || parsed.chainName === undefined ||
AllChains.includes(parsed.chainName as ChainName) AllChains.includes(parsed.chainName as CoreChainName)
); );
}) })
.map((idAndAddress: any) => .map((idAndAddress: any) =>
@ -281,7 +279,7 @@ class ContextFunder {
// which require credentials to fetch. If you want to avoid requiring credentials, use // which require credentials to fetch. If you want to avoid requiring credentials, use
// fromSerializedAddressFile instead. // fromSerializedAddressFile instead.
static async fromContext( static async fromContext(
multiProvider: MultiProvider<any>, multiProvider: MultiProvider,
context: Contexts, context: Contexts,
rolesToFund: KEY_ROLE_ENUM[], rolesToFund: KEY_ROLE_ENUM[],
) { ) {
@ -322,7 +320,7 @@ class ContextFunder {
const entries = AllChains.map((c) => { const entries = AllChains.map((c) => {
return [c, []]; return [c, []];
}); });
const chainKeys: CompleteChainMap<BaseCloudAgentKey[]> = const chainKeys: ChainMap<BaseCloudAgentKey[]> =
Object.fromEntries(entries); Object.fromEntries(entries);
for (const role of this.rolesToFund) { for (const role of this.rolesToFund) {
const keys = this.getKeysWithRole(role); const keys = this.getKeysWithRole(role);
@ -348,8 +346,8 @@ class ContextFunder {
key: BaseCloudAgentKey, key: BaseCloudAgentKey,
chain: ChainName, chain: ChainName,
): Promise<boolean> { ): Promise<boolean> {
const chainConnection = this.multiProvider.tryGetChainConnection(chain); const provider = this.multiProvider.tryGetProvider(chain);
if (!chainConnection) { if (!provider) {
error('Cannot get chain connection', { error('Cannot get chain connection', {
chain, chain,
}); });
@ -361,24 +359,27 @@ class ContextFunder {
let failureOccurred = false; let failureOccurred = false;
try { try {
await this.fundKeyIfRequired(chainConnection, chain, key, desiredBalance); await this.fundKeyIfRequired(chain, key, desiredBalance);
} catch (err) { } catch (err) {
error('Error funding key', { error('Error funding key', {
key: await getKeyInfo(key, chain, chainConnection), key: await getKeyInfo(
key,
chain,
this.multiProvider.getProvider(chain),
),
context: this.context, context: this.context,
error: err, error: err,
}); });
failureOccurred = true; failureOccurred = true;
} }
await this.updateWalletBalanceGauge(chainConnection, chain); await this.updateWalletBalanceGauge(chain);
return failureOccurred; return failureOccurred;
} }
private async bridgeIfL2(chain: ChainName) { private async bridgeIfL2(chain: ChainName) {
if (L2Chains.includes(chain)) { if (L2Chains.includes(chain)) {
const chainConnection = this.multiProvider.tryGetChainConnection(chain)!; const funderAddress = await this.multiProvider.getSignerAddress(chain)!;
const funderAddress = await chainConnection.getAddress()!;
const desiredBalanceEther = ethers.utils.parseUnits( const desiredBalanceEther = ethers.utils.parseUnits(
desiredBalancePerChain[chain], desiredBalancePerChain[chain],
'ether', 'ether',
@ -387,7 +388,7 @@ class ContextFunder {
// By bridging the funder with 10x the desired balance we save // By bridging the funder with 10x the desired balance we save
// on L1 gas. // on L1 gas.
const bridgeAmount = await this.getFundingAmount( const bridgeAmount = await this.getFundingAmount(
chainConnection, chain,
funderAddress, funderAddress,
desiredBalanceEther.mul(10), desiredBalanceEther.mul(10),
); );
@ -398,11 +399,13 @@ class ContextFunder {
} }
private async getFundingAmount( private async getFundingAmount(
chainConnection: ChainConnection, chain: ChainName,
address: string, address: string,
desiredBalance: BigNumber, desiredBalance: BigNumber,
): Promise<BigNumber> { ): Promise<BigNumber> {
const currentBalance = await chainConnection.provider.getBalance(address); const currentBalance = await this.multiProvider
.getProvider(chain)
.getBalance(address);
const delta = desiredBalance.sub(currentBalance); const delta = desiredBalance.sub(currentBalance);
const minDelta = desiredBalance const minDelta = desiredBalance
.mul(MIN_DELTA_NUMERATOR) .mul(MIN_DELTA_NUMERATOR)
@ -413,7 +416,6 @@ class ContextFunder {
// Tops up the key's balance to the desired balance if the current balance // Tops up the key's balance to the desired balance if the current balance
// is lower than the desired balance by the min delta // is lower than the desired balance by the min delta
private async fundKeyIfRequired( private async fundKeyIfRequired(
chainConnection: ChainConnection,
chain: ChainName, chain: ChainName,
key: BaseCloudAgentKey, key: BaseCloudAgentKey,
desiredBalance: string, desiredBalance: string,
@ -430,12 +432,16 @@ class ContextFunder {
: desiredBalanceEther; : desiredBalanceEther;
const fundingAmount = await this.getFundingAmount( const fundingAmount = await this.getFundingAmount(
chainConnection, chain,
key.address, key.address,
adjustedDesiredBalance, adjustedDesiredBalance,
); );
const keyInfo = await getKeyInfo(key, chain, chainConnection); const keyInfo = await getKeyInfo(
const funderAddress = await chainConnection.getAddress()!; key,
chain,
this.multiProvider.getProvider(chain),
);
const funderAddress = await this.multiProvider.getSignerAddress(chain);
if (fundingAmount.eq(0)) { if (fundingAmount.eq(0)) {
log('Skipping funding for key', { log('Skipping funding for key', {
@ -452,28 +458,28 @@ class ContextFunder {
funder: { funder: {
address: funderAddress, address: funderAddress,
balance: ethers.utils.formatEther( balance: ethers.utils.formatEther(
await chainConnection.signer!.getBalance(), await this.multiProvider.getSigner(chain).getBalance(),
), ),
}, },
context: this.context, context: this.context,
}); });
} }
const tx = await chainConnection.signer!.sendTransaction({ const tx = await this.multiProvider.sendTransaction(chain, {
to: key.address, to: key.address,
value: fundingAmount, value: fundingAmount,
...chainConnection.overrides,
}); });
log('Sent transaction', { log('Sent transaction', {
key: keyInfo, key: keyInfo,
txUrl: chainConnection.getTxUrl(tx), txUrl: this.multiProvider.getExplorerTxUrl(chain, {
hash: tx.transactionHash,
}),
context: this.context, context: this.context,
chain, chain,
}); });
const receipt = await tx.wait(chainConnection.confirmations);
log('Got transaction receipt', { log('Got transaction receipt', {
key: keyInfo, key: keyInfo,
receipt, tx,
context: this.context, context: this.context,
chain, chain,
}); });
@ -481,20 +487,18 @@ class ContextFunder {
private async bridgeToL2(l2Chain: L2Chain, to: string, amount: BigNumber) { private async bridgeToL2(l2Chain: L2Chain, to: string, amount: BigNumber) {
const l1Chain = L2ToL1[l2Chain]; const l1Chain = L2ToL1[l2Chain];
const l1ChainConnection = await this.multiProvider.tryGetChainConnection(
l1Chain,
)!;
const l2ChainConnection = await this.multiProvider.tryGetChainConnection(
l2Chain,
)!;
log('Bridging ETH to L2', { log('Bridging ETH to L2', {
amount: ethers.utils.formatEther(amount), amount: ethers.utils.formatEther(amount),
l1Funder: await getAddressInfo( l1Funder: await getAddressInfo(
await l1ChainConnection.getAddress()!, await this.multiProvider.getSignerAddress(l1Chain),
l1Chain, l1Chain,
l1ChainConnection, this.multiProvider.getProvider(l1Chain),
),
l2Funder: await getAddressInfo(
to,
l2Chain,
this.multiProvider.getProvider(l2Chain),
), ),
l2Funder: await getAddressInfo(to, l2Chain, l2ChainConnection),
}); });
let tx; let tx;
if (l2Chain.includes('optimism')) { if (l2Chain.includes('optimism')) {
@ -504,9 +508,7 @@ class ContextFunder {
} else { } else {
throw new Error(`${l2Chain} is not an L2`); throw new Error(`${l2Chain} is not an L2`);
} }
await this.multiProvider await this.multiProvider.handleTx(l1Chain, tx);
.tryGetChainConnection(L2ToL1[l2Chain])!
.handleTx(tx);
} }
private async bridgeToOptimism( private async bridgeToOptimism(
@ -515,40 +517,33 @@ class ContextFunder {
to: string, to: string,
) { ) {
const l1Chain = L2ToL1[l2Chain]; const l1Chain = L2ToL1[l2Chain];
const l1ChainConnection =
this.multiProvider.tryGetChainConnection(l1Chain)!;
const l2ChainConnection =
this.multiProvider.tryGetChainConnection(l2Chain)!;
const crossChainMessenger = new CrossChainMessenger({ const crossChainMessenger = new CrossChainMessenger({
l1ChainId: ChainNameToDomainId[l1Chain], l1ChainId: this.multiProvider.getDomainId(l1Chain),
l2ChainId: ChainNameToDomainId[l2Chain], l2ChainId: this.multiProvider.getDomainId(l2Chain),
l1SignerOrProvider: l1ChainConnection.signer!, l1SignerOrProvider: this.multiProvider.getSignerOrProvider(l1Chain),
l2SignerOrProvider: l2ChainConnection.provider, l2SignerOrProvider: this.multiProvider.getSignerOrProvider(l2Chain),
}); });
return crossChainMessenger.depositETH(amount, { return crossChainMessenger.depositETH(amount, {
recipient: to, recipient: to,
overrides: l1ChainConnection.overrides, overrides: this.multiProvider.getTransactionOverrides(l1Chain),
}); });
} }
private async bridgeToArbitrum(l2Chain: L2Chain, amount: BigNumber) { private async bridgeToArbitrum(l2Chain: L2Chain, amount: BigNumber) {
const l1Chain = L2ToL1[l2Chain]; const l1Chain = L2ToL1[l2Chain];
const l1ChainConnection = const l2Network = await getL2Network(
this.multiProvider.tryGetChainConnection(l1Chain)!; this.multiProvider.getDomainId(l2Chain),
const l2Network = await getL2Network(ChainNameToDomainId[l2Chain]); );
const ethBridger = new EthBridger(l2Network); const ethBridger = new EthBridger(l2Network);
return ethBridger.deposit({ return ethBridger.deposit({
amount, amount,
l1Signer: l1ChainConnection.signer!, l1Signer: this.multiProvider.getSigner(l1Chain),
overrides: l1ChainConnection.overrides, overrides: this.multiProvider.getTransactionOverrides(l1Chain),
}); });
} }
private async updateWalletBalanceGauge( private async updateWalletBalanceGauge(chain: ChainName) {
chainConnection: ChainConnection, const funderAddress = await this.multiProvider.getSignerAddress(chain);
chain: ChainName,
) {
const funderAddress = await chainConnection.getAddress();
walletBalanceGauge walletBalanceGauge
.labels({ .labels({
chain, chain,
@ -560,7 +555,9 @@ class ContextFunder {
}) })
.set( .set(
parseFloat( parseFloat(
ethers.utils.formatEther(await chainConnection.signer!.getBalance()), ethers.utils.formatEther(
await this.multiProvider.getSigner(chain).getBalance(),
),
), ),
); );
} }
@ -573,13 +570,11 @@ class ContextFunder {
async function getAddressInfo( async function getAddressInfo(
address: string, address: string,
chain: ChainName, chain: ChainName,
chainConnection: ChainConnection, provider: ethers.providers.Provider,
) { ) {
return { return {
chain, chain,
balance: ethers.utils.formatEther( balance: ethers.utils.formatEther(await provider.getBalance(address)),
await chainConnection.provider.getBalance(address),
),
address, address,
}; };
} }
@ -587,10 +582,10 @@ async function getAddressInfo(
async function getKeyInfo( async function getKeyInfo(
key: BaseCloudAgentKey, key: BaseCloudAgentKey,
chain: ChainName, chain: ChainName,
chainConnection: ChainConnection, provider: ethers.providers.Provider,
) { ) {
return { return {
...(await getAddressInfo(key.address, chain, chainConnection)), ...(await getAddressInfo(key.address, chain, provider)),
context: key.context, context: key.context,
originChain: key.chainName, originChain: key.chainName,
role: key.role, role: key.role,

@ -5,14 +5,14 @@ import { HyperlaneCore, objMap, promiseObjAll } from '@hyperlane-xyz/sdk';
import { deployEnvToSdkEnv } from '../../src/config/environment'; import { deployEnvToSdkEnv } from '../../src/config/environment';
import { getEnvironment, getEnvironmentConfig } from '../utils'; import { getEnvironment, getEnvironmentConfig } from '../utils';
// Some arbitrary treshold for now // Some arbitrary threshold for now
const RECLAIM_BALANCE_THRESHOLD = BigNumber.from(10).pow(17); const RECLAIM_BALANCE_THRESHOLD = BigNumber.from(10).pow(17);
async function main() { async function main() {
const environment = await getEnvironment(); const environment = await getEnvironment();
const coreConfig = await getEnvironmentConfig(); const coreConfig = await getEnvironmentConfig();
const multiProvider = await coreConfig.getMultiProvider(); const multiProvider = await coreConfig.getMultiProvider();
const core: HyperlaneCore<any> = HyperlaneCore.fromEnvironment( const core: HyperlaneCore = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider, multiProvider,
); );
@ -22,8 +22,8 @@ async function main() {
); );
const balances = await promiseObjAll( const balances = await promiseObjAll(
multiProvider.map((chain, chainConnection) => { multiProvider.mapKnownChains((chain) => {
const provider = chainConnection.provider; const provider = multiProvider.getProvider(chain);
const paymasterAddress = paymasters[chain].address; const paymasterAddress = paymasters[chain].address;
return provider.getBalance(paymasterAddress); return provider.getBalance(paymasterAddress);
}), }),
@ -39,8 +39,7 @@ async function main() {
return 'N/A'; return 'N/A';
} }
const tx = await paymaster.contract.claim(); const tx = await paymaster.contract.claim();
const chainConnection = multiProvider.getChainConnection(chain); return multiProvider.getExplorerTxUrl(chain, tx);
return chainConnection.getTxUrl(tx);
}), }),
); );

@ -11,13 +11,12 @@ async function check() {
const multiProvider = await config.getMultiProvider(); const multiProvider = await config.getMultiProvider();
// environments union doesn't work well with typescript
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const coreChecker = new HyperlaneCoreChecker<any>( const coreChecker = new HyperlaneCoreChecker(
multiProvider, multiProvider,
core, core,
config.core, config.core,

@ -37,7 +37,7 @@ async function main() {
const configMap = await getConfiguration(environment, multiProvider); const configMap = await getConfiguration(environment, multiProvider);
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const deployer = new HelloWorldDeployer(multiProvider, configMap, core); const deployer = new HelloWorldDeployer(multiProvider, configMap, core);
const dir = path.join( const dir = path.join(
@ -46,11 +46,14 @@ async function main() {
context, context,
); );
let previousContracts: ChainMap<any, HelloWorldContracts> = {}; let previousContracts: ChainMap<HelloWorldContracts> = {};
let existingVerificationInputs = {}; let existingVerificationInputs = {};
try { try {
const addresses = readJSON(dir, 'addresses.json'); const addresses = readJSON(dir, 'addresses.json');
previousContracts = buildContracts(addresses, helloWorldFactories) as any; previousContracts = buildContracts(
addresses,
helloWorldFactories,
) as ChainMap<HelloWorldContracts>;
existingVerificationInputs = readJSON(dir, 'verification.json'); existingVerificationInputs = readJSON(dir, 'verification.json');
} catch (e) { } catch (e) {
console.info(`Could not load previous deployment, file may not exist`); console.info(`Could not load previous deployment, file may not exist`);
@ -66,7 +69,6 @@ async function main() {
writeJSON( writeJSON(
dir, dir,
'addresses.json', 'addresses.json',
// @ts-ignore
serializeContracts(deployer.deployedContracts), serializeContracts(deployer.deployedContracts),
); );
writeJSON( writeJSON(

@ -152,7 +152,7 @@ async function main(): Promise<boolean> {
); );
const gasCalculator = InterchainGasCalculator.fromEnvironment( const gasCalculator = InterchainGasCalculator.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
app.multiProvider as any, app.multiProvider,
); );
const appChains = app.chains(); const appChains = app.chains();
@ -355,10 +355,10 @@ async function main(): Promise<boolean> {
} }
async function sendMessage( async function sendMessage(
app: HelloWorldApp<any>, app: HelloWorldApp,
origin: ChainName, origin: ChainName,
destination: ChainName, destination: ChainName,
gasCalc: InterchainGasCalculator<any>, gasCalc: InterchainGasCalculator,
messageSendTimeout: number, messageSendTimeout: number,
messageReceiptTimeout: number, messageReceiptTimeout: number,
) { ) {
@ -442,7 +442,7 @@ async function sendMessage(
} }
async function messageIsProcessed( async function messageIsProcessed(
core: HyperlaneCore<any>, core: HyperlaneCore,
origin: ChainName, origin: ChainName,
destination: ChainName, destination: ChainName,
message: DispatchedMessage, message: DispatchedMessage,
@ -452,10 +452,10 @@ async function messageIsProcessed(
} }
async function updateWalletBalanceMetricFor( async function updateWalletBalanceMetricFor(
app: HelloWorldApp<any>, app: HelloWorldApp,
chain: ChainName, chain: ChainName,
): Promise<void> { ): Promise<void> {
const provider = app.multiProvider.getChainConnection(chain).provider; const provider = app.multiProvider.getProvider(chain);
const signerAddress = await app const signerAddress = await app
.getContracts(chain) .getContracts(chain)
.router.signer.getAddress(); .router.signer.getAddress();

@ -5,13 +5,10 @@ import {
} from '@hyperlane-xyz/helloworld'; } from '@hyperlane-xyz/helloworld';
import { import {
ChainMap, ChainMap,
ChainName,
HyperlaneCore, HyperlaneCore,
MultiProvider, MultiProvider,
RouterConfig, RouterConfig,
buildContracts, buildContracts,
objMap,
promiseObjAll,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { Contexts } from '../../config/contexts'; import { Contexts } from '../../config/contexts';
@ -21,33 +18,27 @@ import { ConnectionType } from '../../src/config/agent';
import { deployEnvToSdkEnv } from '../../src/config/environment'; import { deployEnvToSdkEnv } from '../../src/config/environment';
import { HelloWorldConfig } from '../../src/config/helloworld'; import { HelloWorldConfig } from '../../src/config/helloworld';
export async function getConfiguration<Chain extends ChainName>( export async function getConfiguration(
environment: DeployEnvironment, environment: DeployEnvironment,
multiProvider: MultiProvider<Chain>, multiProvider: MultiProvider,
): Promise<ChainMap<Chain, RouterConfig>> { ): Promise<ChainMap<RouterConfig>> {
const signerMap = await promiseObjAll( const ownerMap: ChainMap<{ owner: string }> = {};
multiProvider.map(async (_, dc) => dc.signer!), for (const chain of multiProvider.getKnownChainNames()) {
); ownerMap[chain] = {
const ownerMap = await promiseObjAll( owner: await multiProvider.getSignerAddress(chain),
objMap(signerMap, async (_, signer) => { };
return { }
owner: await signer.getAddress(),
};
}),
);
// Currently can't be typed as per https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/594/files#diff-40a12589668de942078f498e0ab0fda512e1eb7397189d6d286b590ae87c45d1R31 const core: HyperlaneCore = HyperlaneCore.fromEnvironment(
// @ts-ignore
const core: HyperlaneCore<Chain> = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
return core.extendWithConnectionClientConfig(ownerMap); return core.extendWithConnectionClientConfig(ownerMap);
} }
export async function getApp<Chain extends ChainName>( export async function getApp(
coreConfig: CoreEnvironmentConfig<Chain>, coreConfig: CoreEnvironmentConfig,
context: Contexts, context: Contexts,
keyRole: KEY_ROLE_ENUM, keyRole: KEY_ROLE_ENUM,
keyContext: Contexts = context, keyContext: Contexts = context,
@ -57,23 +48,23 @@ export async function getApp<Chain extends ChainName>(
const contracts = buildContracts( const contracts = buildContracts(
helloworldConfig.addresses, helloworldConfig.addresses,
helloWorldFactories, helloWorldFactories,
) as ChainMap<Chain, HelloWorldContracts>; ) as ChainMap<HelloWorldContracts>;
const multiProvider: MultiProvider<any> = await coreConfig.getMultiProvider( const multiProvider: MultiProvider = await coreConfig.getMultiProvider(
keyContext, keyContext,
keyRole, keyRole,
connectionType, connectionType,
); );
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[coreConfig.environment], deployEnvToSdkEnv[coreConfig.environment],
multiProvider as any, multiProvider,
) as HyperlaneCore<any>; ) as HyperlaneCore;
return new HelloWorldApp(core, contracts, multiProvider); return new HelloWorldApp(core, contracts, multiProvider);
} }
export function getHelloWorldConfig<Chain extends ChainName>( export function getHelloWorldConfig(
coreConfig: CoreEnvironmentConfig<Chain>, coreConfig: CoreEnvironmentConfig,
context: Contexts, context: Contexts,
): HelloWorldConfig<Chain> { ): HelloWorldConfig {
const helloWorldConfigs = coreConfig.helloWorld; const helloWorldConfigs = coreConfig.helloWorld;
if (!helloWorldConfigs) { if (!helloWorldConfigs) {
throw new Error( throw new Error(

@ -10,10 +10,9 @@ async function main() {
const environment = await getEnvironment(); const environment = await getEnvironment();
const config = getCoreEnvironmentConfig(environment); const config = getCoreEnvironmentConfig(environment);
const multiProvider = await config.getMultiProvider(); const multiProvider = await config.getMultiProvider();
// environments union doesn't work well with typescript
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const validators = Object.entries(config.core).flatMap(([chain, set]) => const validators = Object.entries(config.core).flatMap(([chain, set]) =>
@ -24,7 +23,6 @@ async function main() {
4, 4,
validators, validators,
async ({ chain, validator }) => { async ({ chain, validator }) => {
// @ts-ignore Not sure why I need to do this..
const validatorAnnounce = core.getContracts(chain).validatorAnnounce; const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
const storageLocations = const storageLocations =
await validatorAnnounce.getAnnouncedStorageLocations([validator]); await validatorAnnounce.getAnnouncedStorageLocations([validator]);

@ -4,6 +4,7 @@ import {
ChainMap, ChainMap,
Chains, Chains,
LiquidityLayerApp, LiquidityLayerApp,
LiquidityLayerContracts,
buildContracts, buildContracts,
liquidityLayerFactories, liquidityLayerFactories,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
@ -27,11 +28,10 @@ async function check() {
'middleware/liquidity-layer', 'middleware/liquidity-layer',
); );
const addresses = readJSON(dir, 'addresses.json'); const addresses = readJSON(dir, 'addresses.json');
// @ts-ignore const contracts = buildContracts(
const contracts: ChainMap<any, LiquidityLayerContracts> = buildContracts(
addresses, addresses,
liquidityLayerFactories, liquidityLayerFactories,
); ) as ChainMap<LiquidityLayerContracts>;
const app = new LiquidityLayerApp( const app = new LiquidityLayerApp(
contracts, contracts,
multiProvider, multiProvider,

@ -24,7 +24,7 @@ async function main() {
const multiProvider = await coreConfig.getMultiProvider(); const multiProvider = await coreConfig.getMultiProvider();
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const dir = path.join( const dir = path.join(

@ -23,7 +23,7 @@ async function main() {
const multiProvider = await coreConfig.getMultiProvider(); const multiProvider = await coreConfig.getMultiProvider();
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const dir = path.join( const dir = path.join(

@ -22,7 +22,7 @@ async function main() {
const multiProvider = await coreConfig.getMultiProvider(); const multiProvider = await coreConfig.getMultiProvider();
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
const dir = path.join( const dir = path.join(

@ -3,6 +3,7 @@ import path from 'path';
import { import {
ChainMap, ChainMap,
LiquidityLayerApp, LiquidityLayerApp,
LiquidityLayerContracts,
buildContracts, buildContracts,
liquidityLayerFactories, liquidityLayerFactories,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
@ -26,11 +27,10 @@ async function relayPortalTransfers() {
'middleware/liquidity-layer', 'middleware/liquidity-layer',
); );
const addresses = readJSON(dir, 'addresses.json'); const addresses = readJSON(dir, 'addresses.json');
// @ts-ignore const contracts = buildContracts(
const contracts: ChainMap<any, LiquidityLayerContracts> = buildContracts(
addresses, addresses,
liquidityLayerFactories, liquidityLayerFactories,
); ) as ChainMap<LiquidityLayerContracts>;
const app = new LiquidityLayerApp( const app = new LiquidityLayerApp(
contracts, contracts,
multiProvider, multiProvider,

@ -11,12 +11,7 @@ async function main() {
.require('f').argv; .require('f').argv;
const agentConfig = await getContextAgentConfig(); const agentConfig = await getContextAgentConfig();
const envVars = await getAgentEnvVars<any>( const envVars = await getAgentEnvVars(argv.c, argv.r, agentConfig, argv.i);
argv.c,
argv.r,
agentConfig,
argv.i,
);
await writeFile(argv.f, envVars.join('\n')); await writeFile(argv.f, envVars.join('\n'));
} }

@ -16,7 +16,7 @@ async function deploy() {
await assertCorrectKubeContext(config); await assertCorrectKubeContext(config);
const allChains = Object.keys(config.transactionConfigs); const allChains = Object.keys(config.chainMetadataConfigs);
await Promise.all( await Promise.all(
allChains allChains
.filter((_) => !agentConfig.contextChainNames.includes(_)) .filter((_) => !agentConfig.contextChainNames.includes(_))

@ -33,9 +33,8 @@ async function delegate() {
const { chain, delegate, safe, action } = await getArgs(); const { chain, delegate, safe, action } = await getArgs();
const multiProvider = await config.getMultiProvider(); const multiProvider = await config.getMultiProvider();
const connection = multiProvider.getChainConnection(chain);
const safeService = getSafeService(chain, connection); const safeService = getSafeService(chain, multiProvider);
const delegates = await getSafeDelegates(safeService, safe); const delegates = await getSafeDelegates(safeService, safe);
console.log('Connecting to ledger, ensure plugged in and unlocked...'); console.log('Connecting to ledger, ensure plugged in and unlocked...');

@ -17,7 +17,7 @@ async function deploy() {
const agentConfig = await getContextAgentConfig(config); const agentConfig = await getContextAgentConfig(config);
for (const chain of agentConfig.contextChainNames) { for (const chain of agentConfig.contextChainNames) {
await runAgentHelmCommand<any>(HelmCommand.UpgradeDiff, agentConfig, chain); await runAgentHelmCommand(HelmCommand.UpgradeDiff, agentConfig, chain);
} }
} }

@ -4,8 +4,8 @@ import yargs from 'yargs';
import { import {
AllChains, AllChains,
ChainMap, ChainMap,
ChainMetadata,
ChainName, ChainName,
IChainConnection,
MultiProvider, MultiProvider,
objMap, objMap,
promiseObjAll, promiseObjAll,
@ -55,7 +55,7 @@ export function assertEnvironment(env: string): DeployEnvironment {
export function getCoreEnvironmentConfig<Env extends DeployEnvironment>( export function getCoreEnvironmentConfig<Env extends DeployEnvironment>(
env: Env, env: Env,
): CoreEnvironmentConfig<any> { ): CoreEnvironmentConfig {
return environments[env]; return environments[env];
} }
@ -74,8 +74,8 @@ export async function getContext(defaultContext?: string): Promise<Contexts> {
} }
// Gets the agent config for the context that has been specified via yargs. // Gets the agent config for the context that has been specified via yargs.
export async function getContextAgentConfig<Chain extends ChainName>( export async function getContextAgentConfig(
coreEnvironmentConfig?: CoreEnvironmentConfig<Chain>, coreEnvironmentConfig?: CoreEnvironmentConfig,
defaultContext?: string, defaultContext?: string,
) { ) {
return getAgentConfig( return getAgentConfig(
@ -85,9 +85,9 @@ export async function getContextAgentConfig<Chain extends ChainName>(
} }
// Gets the agent config of a specific context. // Gets the agent config of a specific context.
export async function getAgentConfig<Chain extends ChainName>( export async function getAgentConfig(
context: Contexts, context: Contexts,
coreEnvironmentConfig?: CoreEnvironmentConfig<Chain>, coreEnvironmentConfig?: CoreEnvironmentConfig,
) { ) {
const coreConfig = coreEnvironmentConfig const coreConfig = coreEnvironmentConfig
? coreEnvironmentConfig ? coreEnvironmentConfig
@ -103,10 +103,10 @@ export async function getAgentConfig<Chain extends ChainName>(
return agentConfig; return agentConfig;
} }
async function getKeyForRole<Chain extends ChainName>( async function getKeyForRole(
environment: DeployEnvironment, environment: DeployEnvironment,
context: Contexts, context: Contexts,
chain: Chain, chain: ChainName,
role: KEY_ROLE_ENUM, role: KEY_ROLE_ENUM,
index?: number, index?: number,
): Promise<CloudAgentKey> { ): Promise<CloudAgentKey> {
@ -115,14 +115,14 @@ async function getKeyForRole<Chain extends ChainName>(
return getCloudAgentKey(agentConfig, role, chain, index); return getCloudAgentKey(agentConfig, role, chain, index);
} }
export async function getMultiProviderForRole<Chain extends ChainName>( export async function getMultiProviderForRole(
txConfigs: ChainMap<Chain, IChainConnection>, txConfigs: ChainMap<ChainMetadata>,
environment: DeployEnvironment, environment: DeployEnvironment,
context: Contexts, context: Contexts,
role: KEY_ROLE_ENUM, role: KEY_ROLE_ENUM,
index?: number, index?: number,
connectionType?: ConnectionType, connectionType?: ConnectionType,
): Promise<MultiProvider<Chain>> { ): Promise<MultiProvider> {
const connections = await promiseObjAll( const connections = await promiseObjAll(
objMap(txConfigs, async (chain, config) => { objMap(txConfigs, async (chain, config) => {
const provider = await fetchProvider(environment, chain, connectionType); const provider = await fetchProvider(environment, chain, connectionType);
@ -135,7 +135,7 @@ export async function getMultiProviderForRole<Chain extends ChainName>(
}; };
}), }),
); );
return new MultiProvider<Chain>(connections); return new MultiProvider(connections);
} }
export function getCoreContractsSdkFilepath() { export function getCoreContractsSdkFilepath() {
@ -173,8 +173,8 @@ export function getKeyRoleAndChainArgs() {
.number('i'); .number('i');
} }
export async function assertCorrectKubeContext<Chain extends ChainName>( export async function assertCorrectKubeContext(
coreConfig: CoreEnvironmentConfig<Chain>, coreConfig: CoreEnvironmentConfig,
) { ) {
const currentKubeContext = await getCurrentKubernetesContext(); const currentKubeContext = await getCurrentKubernetesContext();
if ( if (

@ -9,14 +9,12 @@ async function main() {
const environment = await getEnvironment(); const environment = await getEnvironment();
const config = getCoreEnvironmentConfig(environment); const config = getCoreEnvironmentConfig(environment);
const multiProvider = await config.getMultiProvider(); const multiProvider = await config.getMultiProvider();
// environments union doesn't work well with typescript
const core = HyperlaneCore.fromEnvironment( const core = HyperlaneCore.fromEnvironment(
deployEnvToSdkEnv[environment], deployEnvToSdkEnv[environment],
multiProvider as any, multiProvider,
); );
objMap(config.core, async (chain, coreConfig) => { objMap(config.core, async (chain, coreConfig) => {
// @ts-ignore Not sure why I need to do this..
const validatorAnnounce = core.getContracts(chain).validatorAnnounce; const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
const storageLocations = const storageLocations =
await validatorAnnounce.getAnnouncedStorageLocations( await validatorAnnounce.getAnnouncedStorageLocations(

@ -1,6 +1,6 @@
import { import {
ChainMap,
CompilerOptions, CompilerOptions,
CompleteChainMap,
ContractVerifier, ContractVerifier,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
@ -54,7 +54,7 @@ async function main() {
await execCmd(`solc-select use ${matches[1]}`); await execCmd(`solc-select use ${matches[1]}`);
await execCmd(`solc ${sourcePath}`); await execCmd(`solc ${sourcePath}`);
const apiKeys: CompleteChainMap<string> = await fetchGCPSecret( const apiKeys: ChainMap<string> = await fetchGCPSecret(
'explorer-api-keys', 'explorer-api-keys',
true, true,
); );

@ -43,7 +43,7 @@ export class AgentAwsKey extends CloudAgentKey {
public remoteKey: RemoteKey = { fetched: false }; public remoteKey: RemoteKey = { fetched: false };
constructor( constructor(
agentConfig: AgentConfig<any>, agentConfig: AgentConfig,
role: KEY_ROLE_ENUM, role: KEY_ROLE_ENUM,
chainName?: ChainName, chainName?: ChainName,
index?: number, index?: number,

@ -21,7 +21,7 @@ import { KEY_ROLE_ENUM } from '../roles';
import { AgentAwsKey } from './key'; import { AgentAwsKey } from './key';
export class AgentAwsUser<Chain extends ChainName> { export class AgentAwsUser {
private adminIamClient: IAMClient; private adminIamClient: IAMClient;
private _arn: string | undefined; private _arn: string | undefined;
@ -31,7 +31,7 @@ export class AgentAwsUser<Chain extends ChainName> {
public readonly context: Contexts, public readonly context: Contexts,
public readonly role: KEY_ROLE_ENUM, public readonly role: KEY_ROLE_ENUM,
public readonly region: string, public readonly region: string,
public readonly chainName?: Chain, public readonly chainName?: ChainName,
) { ) {
this.adminIamClient = new IAMClient({ region }); this.adminIamClient = new IAMClient({ region });
} }
@ -106,11 +106,11 @@ export class AgentAwsUser<Chain extends ChainName> {
); );
} }
key(agentConfig: AgentConfig<any>): AgentAwsKey { key(agentConfig: AgentConfig): AgentAwsKey {
return new AgentAwsKey(agentConfig, this.role, this.chainName); return new AgentAwsKey(agentConfig, this.role, this.chainName);
} }
async createKeyIfNotExists(agentConfig: AgentConfig<Chain>) { async createKeyIfNotExists(agentConfig: AgentConfig) {
const key = this.key(agentConfig); const key = this.key(agentConfig);
await key.createIfNotExists(); await key.createIfNotExists();
await key.putKeyPolicy(this.arn); await key.putKeyPolicy(this.arn);

@ -14,15 +14,13 @@ import { KEY_ROLE_ENUM } from '../roles';
import { AgentAwsKey } from './key'; import { AgentAwsKey } from './key';
import { AgentAwsUser } from './user'; import { AgentAwsUser } from './user';
export class ValidatorAgentAwsUser< export class ValidatorAgentAwsUser extends AgentAwsUser {
Chain extends ChainName,
> extends AgentAwsUser<Chain> {
private adminS3Client: S3Client; private adminS3Client: S3Client;
constructor( constructor(
environment: string, environment: string,
context: Contexts, context: Contexts,
public readonly chainName: Chain, public readonly chainName: ChainName,
public readonly index: number, public readonly index: number,
region: string, region: string,
public readonly bucket: string, public readonly bucket: string,
@ -85,7 +83,7 @@ export class ValidatorAgentAwsUser<
await this.adminS3Client.send(cmd); await this.adminS3Client.send(cmd);
} }
key(agentConfig: AgentConfig<Chain>): AgentAwsKey { key(agentConfig: AgentConfig): AgentAwsKey {
return new AgentAwsKey(agentConfig, this.role, this.chainName, this.index); return new AgentAwsKey(agentConfig, this.role, this.chainName, this.index);
} }

@ -25,9 +25,9 @@ import { KEY_ROLE_ENUM } from './roles';
const helmChartPath = '../../rust/helm/hyperlane-agent/'; const helmChartPath = '../../rust/helm/hyperlane-agent/';
async function helmValuesForChain<Chain extends ChainName>( async function helmValuesForChain(
chainName: Chain, chainName: ChainName,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
) { ) {
const chainAgentConfig = new ChainAgentConfig(agentConfig, chainName); const chainAgentConfig = new ChainAgentConfig(agentConfig, chainName);
const gelatoApiKeyRequired = const gelatoApiKeyRequired =
@ -94,10 +94,10 @@ async function helmValuesForChain<Chain extends ChainName>(
}; };
} }
export async function getAgentEnvVars<Chain extends ChainName>( export async function getAgentEnvVars(
outboxChainName: Chain, outboxChainName: ChainName,
role: KEY_ROLE_ENUM, role: KEY_ROLE_ENUM,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
index?: number, index?: number,
) { ) {
const chainNames = agentConfig.contextChainNames; const chainNames = agentConfig.contextChainNames;
@ -165,7 +165,7 @@ export async function getAgentEnvVars<Chain extends ChainName>(
} else { } else {
// AWS keys // AWS keys
let user: AgentAwsUser<Chain>; let user: AgentAwsUser;
if (role === KEY_ROLE_ENUM.Validator && agentConfig.validators) { if (role === KEY_ROLE_ENUM.Validator && agentConfig.validators) {
const checkpointSyncer = const checkpointSyncer =
@ -271,9 +271,7 @@ function configEnvVars(
return envVars; return envVars;
} }
export async function getSecretAwsCredentials<Chain extends ChainName>( export async function getSecretAwsCredentials(agentConfig: AgentConfig) {
agentConfig: AgentConfig<Chain>,
) {
return { return {
accessKeyId: await fetchGCPSecret( accessKeyId: await fetchGCPSecret(
`${agentConfig.runEnv}-aws-access-key-id`, `${agentConfig.runEnv}-aws-access-key-id`,
@ -312,10 +310,7 @@ export async function getSecretDeployerKey(
return key.privateKey; return key.privateKey;
} }
async function getSecretRpcEndpoints<Chain extends ChainName>( async function getSecretRpcEndpoints(agentConfig: AgentConfig, quorum = false) {
agentConfig: AgentConfig<Chain>,
quorum = false,
) {
const environment = agentConfig.runEnv; const environment = agentConfig.runEnv;
return Object.fromEntries( return Object.fromEntries(
agentConfig.contextChainNames.map((chainName) => [ agentConfig.contextChainNames.map((chainName) => [
@ -325,9 +320,9 @@ async function getSecretRpcEndpoints<Chain extends ChainName>(
); );
} }
export async function doesAgentReleaseExist<Chain extends ChainName>( export async function doesAgentReleaseExist(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
outboxChainName: Chain, outboxChainName: ChainName,
) { ) {
try { try {
await execCmd( await execCmd(
@ -345,10 +340,10 @@ export async function doesAgentReleaseExist<Chain extends ChainName>(
} }
} }
export async function runAgentHelmCommand<Chain extends ChainName>( export async function runAgentHelmCommand(
action: HelmCommand, action: HelmCommand,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
outboxChainName: Chain, outboxChainName: ChainName,
) { ) {
if (action === HelmCommand.Remove) { if (action === HelmCommand.Remove) {
return execCmd( return execCmd(
@ -408,9 +403,9 @@ export async function runAgentHelmCommand<Chain extends ChainName>(
return; return;
} }
function getHelmReleaseName<Chain extends ChainName>( function getHelmReleaseName(
outboxChainName: Chain, outboxChainName: ChainName,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
): string { ): string {
// For backward compatibility reasons, don't include the context // For backward compatibility reasons, don't include the context
// in the name of the helm release if the context is the default "hyperlane" // in the name of the helm release if the context is the default "hyperlane"

@ -15,10 +15,10 @@ interface KeyAsAddress {
address: string; address: string;
} }
export function getCloudAgentKey<Chain extends ChainName>( export function getCloudAgentKey(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
role: KEY_ROLE_ENUM, role: KEY_ROLE_ENUM,
chainName?: Chain, chainName?: ChainName,
index?: number, index?: number,
): CloudAgentKey { ): CloudAgentKey {
if ( if (
@ -40,7 +40,7 @@ export function getCloudAgentKey<Chain extends ChainName>(
} }
export function getValidatorCloudAgentKeys( export function getValidatorCloudAgentKeys(
agentConfig: AgentConfig<any>, agentConfig: AgentConfig,
): Array<CloudAgentKey> { ): Array<CloudAgentKey> {
// For each chainName, create validatorCount keys // For each chainName, create validatorCount keys
return agentConfig.contextChainNames.flatMap((chainName) => { return agentConfig.contextChainNames.flatMap((chainName) => {
@ -60,7 +60,7 @@ export function getValidatorCloudAgentKeys(
} }
export function getRelayerCloudAgentKeys( export function getRelayerCloudAgentKeys(
agentConfig: AgentConfig<any>, agentConfig: AgentConfig,
): Array<CloudAgentKey> { ): Array<CloudAgentKey> {
return agentConfig.contextChainNames.map((chainName) => return agentConfig.contextChainNames.map((chainName) =>
getCloudAgentKey(agentConfig, KEY_ROLE_ENUM.Relayer, chainName), getCloudAgentKey(agentConfig, KEY_ROLE_ENUM.Relayer, chainName),
@ -68,7 +68,7 @@ export function getRelayerCloudAgentKeys(
} }
export function getAllCloudAgentKeys( export function getAllCloudAgentKeys(
agentConfig: AgentConfig<any>, agentConfig: AgentConfig,
): Array<CloudAgentKey> { ): Array<CloudAgentKey> {
return agentConfig.rolesWithKeys.flatMap((role) => { return agentConfig.rolesWithKeys.flatMap((role) => {
if (role === KEY_ROLE_ENUM.Validator) { if (role === KEY_ROLE_ENUM.Validator) {
@ -81,7 +81,7 @@ export function getAllCloudAgentKeys(
}); });
} }
export async function deleteAgentKeys(agentConfig: AgentConfig<any>) { export async function deleteAgentKeys(agentConfig: AgentConfig) {
const keys = getAllCloudAgentKeys(agentConfig); const keys = getAllCloudAgentKeys(agentConfig);
await Promise.all(keys.map((key) => key.delete())); await Promise.all(keys.map((key) => key.delete()));
await execCmd( await execCmd(
@ -92,9 +92,7 @@ export async function deleteAgentKeys(agentConfig: AgentConfig<any>) {
); );
} }
export async function createAgentKeysIfNotExists( export async function createAgentKeysIfNotExists(agentConfig: AgentConfig) {
agentConfig: AgentConfig<any>,
) {
const keys = getAllCloudAgentKeys(agentConfig); const keys = getAllCloudAgentKeys(agentConfig);
await Promise.all( await Promise.all(
@ -110,10 +108,10 @@ export async function createAgentKeysIfNotExists(
); );
} }
export async function rotateKey<Chain extends ChainName>( export async function rotateKey(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
role: KEY_ROLE_ENUM, role: KEY_ROLE_ENUM,
chainName: Chain, chainName: ChainName,
) { ) {
const key = getCloudAgentKey(agentConfig, role, chainName); const key = getCloudAgentKey(agentConfig, role, chainName);
await key.update(); await key.update();
@ -150,9 +148,9 @@ async function persistAddresses(
} }
// This function returns all keys for a given outbox chain in a dictionary where the key is the identifier // This function returns all keys for a given outbox chain in a dictionary where the key is the identifier
export async function fetchKeysForChain<Chain extends ChainName>( export async function fetchKeysForChain(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
chainName: Chain, chainName: ChainName,
): Promise<Record<string, CloudAgentKey>> { ): Promise<Record<string, CloudAgentKey>> {
// Get all keys for the chainName. Include keys where chainName is undefined, // Get all keys for the chainName. Include keys where chainName is undefined,
// which are keys that are not chain-specific but should still be included // which are keys that are not chain-specific but should still be included

@ -13,15 +13,15 @@ import { gcpSecretExists } from '../utils/gcloud';
import { DeployEnvironment } from './environment'; import { DeployEnvironment } from './environment';
// Allows a "default" config to be specified and any per-chain overrides. // Allows a "default" config to be specified and any per-chain overrides.
interface ChainOverridableConfig<Chain extends ChainName, T> { interface ChainOverridableConfig<T> {
default: T; default: T;
chainOverrides?: Partial<ChainMap<Chain, Partial<T>>>; chainOverrides?: ChainMap<Partial<T>>;
} }
// Returns the default config with any overriden values specified for the provided chain. // Returns the default config with any overridden values specified for the provided chain.
export function getChainOverriddenConfig<Chain extends ChainName, T>( export function getChainOverriddenConfig<T>(
overridableConfig: ChainOverridableConfig<Chain, T>, overridableConfig: ChainOverridableConfig<T>,
chain: Chain, chain: ChainName,
): T { ): T {
return { return {
...overridableConfig.default, ...overridableConfig.default,
@ -75,10 +75,7 @@ interface BaseRelayerConfig {
} }
// Per-chain relayer agent configs // Per-chain relayer agent configs
type ChainRelayerConfigs<Chain extends ChainName> = ChainOverridableConfig< type ChainRelayerConfigs = ChainOverridableConfig<BaseRelayerConfig>;
Chain,
BaseRelayerConfig
>;
interface SerializableGasPaymentEnforcementConfig interface SerializableGasPaymentEnforcementConfig
extends Omit<GasPaymentEnforcementConfig, 'whitelist'> { extends Omit<GasPaymentEnforcementConfig, 'whitelist'> {
@ -149,10 +146,7 @@ interface ValidatorChainConfig {
} }
// Validator agents for each chain. // Validator agents for each chain.
export type ChainValidatorConfigs<Chain extends ChainName> = ChainMap< export type ChainValidatorConfigs = ChainMap<ValidatorChainConfig>;
Chain,
ValidatorChainConfig
>;
// Helm config for a single validator // Helm config for a single validator
interface ValidatorHelmConfig { interface ValidatorHelmConfig {
@ -198,9 +192,9 @@ export interface DockerConfig {
tag: string; tag: string;
} }
export interface GelatoConfig<Chain extends ChainName> { export interface GelatoConfig {
// List of chains in which using Gelato is enabled for // List of chains in which using Gelato is enabled for
enabledChains: Chain[]; enabledChains: ChainName[];
} }
export enum TransactionSubmissionType { export enum TransactionSubmissionType {
@ -208,7 +202,7 @@ export enum TransactionSubmissionType {
Gelato = 'gelato', Gelato = 'gelato',
} }
export interface AgentConfig<Chain extends ChainName> { export interface AgentConfig {
environment: string; environment: string;
namespace: string; namespace: string;
runEnv: DeployEnvironment; runEnv: DeployEnvironment;
@ -219,13 +213,13 @@ export interface AgentConfig<Chain extends ChainName> {
index?: IndexingConfig; index?: IndexingConfig;
aws?: AwsConfig; aws?: AwsConfig;
// Names of all chains in the environment // Names of all chains in the environment
environmentChainNames: Chain[]; environmentChainNames: ChainName[];
// Names of chains this context cares about // Names of chains this context cares about
contextChainNames: Chain[]; contextChainNames: ChainName[];
gelato?: GelatoConfig<Chain>; gelato?: GelatoConfig;
// RC contexts do not provide validators // RC contexts do not provide validators
validators?: ChainValidatorConfigs<Chain>; validators?: ChainValidatorConfigs;
relayer?: ChainRelayerConfigs<Chain>; relayer?: ChainRelayerConfigs;
// Roles to manage keys for // Roles to manage keys for
rolesWithKeys: KEY_ROLE_ENUM[]; rolesWithKeys: KEY_ROLE_ENUM[];
} }
@ -267,9 +261,9 @@ export type RustChainSetup = {
index?: { from: string }; index?: { from: string };
}; };
export type RustConfig<Chain extends ChainName> = { export type RustConfig = {
environment: DeployEnvironment; environment: DeployEnvironment;
chains: Partial<ChainMap<Chain, RustChainSetup>>; chains: Partial<ChainMap<RustChainSetup>>;
// TODO: Separate DBs for each chain (fold into RustChainSetup) // TODO: Separate DBs for each chain (fold into RustChainSetup)
db: string; db: string;
tracing: { tracing: {
@ -279,10 +273,10 @@ export type RustConfig<Chain extends ChainName> = {
}; };
// Helper to get chain-specific agent configurations // Helper to get chain-specific agent configurations
export class ChainAgentConfig<Chain extends ChainName> { export class ChainAgentConfig {
constructor( constructor(
public readonly agentConfig: AgentConfig<Chain>, public readonly agentConfig: AgentConfig,
public readonly chainName: Chain, public readonly chainName: ChainName,
) {} ) {}
// Credentials are only needed if AWS keys are needed -- otherwise, the // Credentials are only needed if AWS keys are needed -- otherwise, the
@ -475,7 +469,7 @@ export class ChainAgentConfig<Chain extends ChainName> {
} }
} }
transactionSubmissionType(chain: Chain): TransactionSubmissionType { transactionSubmissionType(chain: ChainName): TransactionSubmissionType {
if (this.agentConfig.gelato?.enabledChains.includes(chain)) { if (this.agentConfig.gelato?.enabledChains.includes(chain)) {
return TransactionSubmissionType.Gelato; return TransactionSubmissionType.Gelato;
} }

@ -1,7 +1,6 @@
import { FallbackProviderConfig } from '@ethersproject/providers'; import { FallbackProviderConfig } from '@ethersproject/providers';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { StaticCeloJsonRpcProvider } from '@hyperlane-xyz/celo-ethers-provider';
import { ChainName, RetryJsonRpcProvider } from '@hyperlane-xyz/sdk'; import { ChainName, RetryJsonRpcProvider } from '@hyperlane-xyz/sdk';
import { getSecretRpcEndpoint } from '../agents'; import { getSecretRpcEndpoint } from '../agents';
@ -9,15 +8,7 @@ import { getSecretRpcEndpoint } from '../agents';
import { ConnectionType } from './agent'; import { ConnectionType } from './agent';
import { DeployEnvironment } from './environment'; import { DeployEnvironment } from './environment';
const CELO_CHAIN_NAMES = new Set(['alfajores', 'baklava', 'celo']); const providerBuilder = (url: string, retry = true) => {
const providerBuilder = (url: string, chainName: ChainName, retry = true) => {
// TODO: get StaticCeloJsonRpcProvider to be compatible with the RetryJsonRpcProvider.
// For now, the two are incompatible, so even if retrying is requested for a Celo chain,
// we don't use a RetryJsonRpcProvider.
if (CELO_CHAIN_NAMES.has(chainName)) {
return new StaticCeloJsonRpcProvider(url);
}
const baseProvider = new ethers.providers.JsonRpcProvider(url); const baseProvider = new ethers.providers.JsonRpcProvider(url);
return retry return retry
? new RetryJsonRpcProvider(baseProvider, { ? new RetryJsonRpcProvider(baseProvider, {
@ -36,20 +27,18 @@ export async function fetchProvider(
const rpcData = await getSecretRpcEndpoint(environment, chainName, !single); const rpcData = await getSecretRpcEndpoint(environment, chainName, !single);
switch (connectionType) { switch (connectionType) {
case ConnectionType.Http: { case ConnectionType.Http: {
return providerBuilder(rpcData, chainName); return providerBuilder(rpcData);
} }
case ConnectionType.HttpQuorum: { case ConnectionType.HttpQuorum: {
return new ethers.providers.FallbackProvider( return new ethers.providers.FallbackProvider(
(rpcData as string[]).map((url) => (rpcData as string[]).map((url) => providerBuilder(url, false)), // disable retry for quorum
providerBuilder(url, chainName, false),
), // disable retry for quorum
); );
} }
case ConnectionType.HttpFallback: { case ConnectionType.HttpFallback: {
return new ethers.providers.FallbackProvider( return new ethers.providers.FallbackProvider(
(rpcData as string[]).map((url, index) => { (rpcData as string[]).map((url, index) => {
const fallbackProviderConfig: FallbackProviderConfig = { const fallbackProviderConfig: FallbackProviderConfig = {
provider: providerBuilder(url, chainName), provider: providerBuilder(url),
// Priority is used by the FallbackProvider to determine // Priority is used by the FallbackProvider to determine
// how to order providers using ascending ordering. // how to order providers using ascending ordering.
// When not specified, all providers have the same priority // When not specified, all providers have the same priority

@ -1,8 +1,8 @@
import { import {
ChainMap, ChainMap,
ChainMetadata,
ChainName, ChainName,
CoreConfig, CoreConfig,
EnvironmentConfig,
MultiProvider, MultiProvider,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { CoreEnvironment } from '@hyperlane-xyz/sdk/dist/core/HyperlaneCore'; import { CoreEnvironment } from '@hyperlane-xyz/sdk/dist/core/HyperlaneCore';
@ -24,19 +24,19 @@ export type EnvironmentChain<E extends DeployEnvironment> = Extract<
ChainName ChainName
>; >;
export type CoreEnvironmentConfig<Chain extends ChainName> = { export type CoreEnvironmentConfig = {
environment: DeployEnvironment; environment: DeployEnvironment;
transactionConfigs: EnvironmentConfig<Chain>; chainMetadataConfigs: ChainMap<ChainMetadata>;
// Each AgentConfig, keyed by the context // Each AgentConfig, keyed by the context
agents: Partial<Record<Contexts, AgentConfig<Chain>>>; agents: Partial<Record<Contexts, AgentConfig>>;
core: ChainMap<Chain, CoreConfig>; core: ChainMap<CoreConfig>;
infra: InfrastructureConfig; infra: InfrastructureConfig;
getMultiProvider: ( getMultiProvider: (
context?: Contexts, context?: Contexts,
role?: KEY_ROLE_ENUM, role?: KEY_ROLE_ENUM,
connectionType?: ConnectionType, connectionType?: ConnectionType,
) => Promise<MultiProvider<Chain>>; ) => Promise<MultiProvider>;
helloWorld?: Partial<Record<Contexts, HelloWorldConfig<Chain>>>; helloWorld?: Partial<Record<Contexts, HelloWorldConfig>>;
keyFunderConfig?: KeyFunderConfig; keyFunderConfig?: KeyFunderConfig;
liquidityLayerRelayerConfig?: LiquidityLayerRelayerConfig; liquidityLayerRelayerConfig?: LiquidityLayerRelayerConfig;
}; };

@ -9,11 +9,11 @@ export enum HelloWorldKathyRunMode {
Service, Service,
} }
export interface HelloWorldKathyConfig<Chain extends ChainName> { export interface HelloWorldKathyConfig {
docker: DockerConfig; docker: DockerConfig;
runEnv: string; runEnv: string;
namespace: string; namespace: string;
chainsToSkip: Chain[]; chainsToSkip: ChainName[];
runConfig: runConfig:
| { | {
mode: HelloWorldKathyRunMode.CycleOnce; mode: HelloWorldKathyRunMode.CycleOnce;
@ -34,7 +34,7 @@ export interface HelloWorldKathyConfig<Chain extends ChainName> {
cyclesBetweenEthereumMessages?: number; cyclesBetweenEthereumMessages?: number;
} }
export interface HelloWorldConfig<Chain extends ChainName> { export interface HelloWorldConfig {
addresses: ChainMap<Chain, { router: string }>; addresses: ChainMap<{ router: string }>;
kathy: HelloWorldKathyConfig<Chain>; kathy: HelloWorldKathyConfig;
} }

@ -24,22 +24,20 @@ import { DeployEnvironment, RustChainSetup, RustConfig } from '../config';
import { ConnectionType } from '../config/agent'; import { ConnectionType } from '../config/agent';
import { writeJSON } from '../utils/utils'; import { writeJSON } from '../utils/utils';
export class HyperlaneCoreInfraDeployer< export class HyperlaneCoreInfraDeployer extends HyperlaneCoreDeployer {
Chain extends ChainName,
> extends HyperlaneCoreDeployer<Chain> {
environment: DeployEnvironment; environment: DeployEnvironment;
constructor( constructor(
multiProvider: MultiProvider<Chain>, multiProvider: MultiProvider,
configMap: ChainMap<Chain, CoreConfig>, configMap: ChainMap<CoreConfig>,
environment: DeployEnvironment, environment: DeployEnvironment,
) { ) {
super(multiProvider, configMap); super(multiProvider, configMap);
this.environment = environment; this.environment = environment;
} }
async deployInterchainGasPaymaster<LocalChain extends Chain>( async deployInterchainGasPaymaster(
chain: LocalChain, chain: ChainName,
proxyAdmin: ProxyAdmin, proxyAdmin: ProxyAdmin,
): Promise< ): Promise<
ProxiedContract<InterchainGasPaymaster, TransparentProxyAddresses> ProxiedContract<InterchainGasPaymaster, TransparentProxyAddresses>
@ -53,8 +51,8 @@ export class HyperlaneCoreInfraDeployer<
return super.deployInterchainGasPaymaster(chain, proxyAdmin, deployOpts); return super.deployInterchainGasPaymaster(chain, proxyAdmin, deployOpts);
} }
async deployDefaultIsmInterchainGasPaymaster<LocalChain extends Chain>( async deployDefaultIsmInterchainGasPaymaster(
chain: LocalChain, chain: ChainName,
interchainGasPaymasterAddress: types.Address, interchainGasPaymasterAddress: types.Address,
): Promise<OverheadIgp> { ): Promise<OverheadIgp> {
const deployOpts = { const deployOpts = {
@ -70,8 +68,8 @@ export class HyperlaneCoreInfraDeployer<
); );
} }
async deployMailbox<LocalChain extends Chain>( async deployMailbox(
chain: LocalChain, chain: ChainName,
defaultIsmAddress: types.Address, defaultIsmAddress: types.Address,
proxyAdmin: ProxyAdmin, proxyAdmin: ProxyAdmin,
): Promise<ProxiedContract<Mailbox, TransparentProxyAddresses>> { ): Promise<ProxiedContract<Mailbox, TransparentProxyAddresses>> {
@ -89,8 +87,8 @@ export class HyperlaneCoreInfraDeployer<
); );
} }
async deployValidatorAnnounce<LocalChain extends Chain>( async deployValidatorAnnounce(
chain: LocalChain, chain: ChainName,
mailboxAddress: types.Address, mailboxAddress: types.Address,
): Promise<ValidatorAnnounce> { ): Promise<ValidatorAnnounce> {
const deployOpts = { const deployOpts = {
@ -103,7 +101,7 @@ export class HyperlaneCoreInfraDeployer<
} }
writeRustConfigs(directory: string) { writeRustConfigs(directory: string) {
const rustConfig: RustConfig<Chain> = { const rustConfig: RustConfig = {
environment: this.environment, environment: this.environment,
chains: {}, chains: {},
db: 'db_path', db: 'db_path',
@ -127,7 +125,7 @@ export class HyperlaneCoreInfraDeployer<
const chainConfig: RustChainSetup = { const chainConfig: RustChainSetup = {
name: chain, name: chain,
domain: metadata.id.toString(), domain: metadata.chainId.toString(),
addresses: { addresses: {
mailbox: contracts.mailbox.contract.address, mailbox: contracts.mailbox.contract.address,
interchainGasPaymaster: contracts.interchainGasPaymaster.address, interchainGasPaymaster: contracts.interchainGasPaymaster.address,
@ -135,7 +133,7 @@ export class HyperlaneCoreInfraDeployer<
}, },
signer: null, signer: null,
protocol: 'ethereum', protocol: 'ethereum',
finalityBlocks: metadata.blocks.reorgPeriod.toString(), finalityBlocks: metadata.blocks!.reorgPeriod!.toString(),
connection: { connection: {
type: ConnectionType.Http, type: ConnectionType.Http,
url: '', url: '',

@ -4,7 +4,6 @@ import { InterchainGasPaymaster__factory } from '@hyperlane-xyz/core';
import { import {
ChainMap, ChainMap,
ChainName, ChainName,
ChainNameToDomainId,
CoreContracts, CoreContracts,
CoreViolationType, CoreViolationType,
EnrolledValidatorsViolation, EnrolledValidatorsViolation,
@ -39,12 +38,12 @@ type AnnotatedCallData = types.CallData & {
description: string; description: string;
}; };
export class HyperlaneCoreGovernor<Chain extends ChainName> { export class HyperlaneCoreGovernor {
readonly checker: HyperlaneCoreChecker<Chain>; readonly checker: HyperlaneCoreChecker;
private calls: ChainMap<Chain, AnnotatedCallData[]>; private calls: ChainMap<AnnotatedCallData[]>;
private canPropose: ChainMap<Chain, Map<string, boolean>>; private canPropose: ChainMap<Map<string, boolean>>;
constructor(checker: HyperlaneCoreChecker<Chain>) { constructor(checker: HyperlaneCoreChecker) {
this.checker = checker; this.checker = checker;
this.calls = objMap(this.checker.app.contractsMap, () => []); this.calls = objMap(this.checker.app.contractsMap, () => []);
this.canPropose = objMap(this.checker.app.contractsMap, () => new Map()); this.canPropose = objMap(this.checker.app.contractsMap, () => new Map());
@ -59,12 +58,12 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
// 3. Prompt the user to confirm that the count, description, // 3. Prompt the user to confirm that the count, description,
// and submission methods look correct before submitting. // and submission methods look correct before submitting.
for (const chain of Object.keys(this.calls) as Chain[]) { for (const chain of Object.keys(this.calls)) {
await this.sendCalls(chain); await this.sendCalls(chain);
} }
} }
protected async sendCalls(chain: Chain) { protected async sendCalls(chain: ChainName) {
const calls = this.calls[chain]; const calls = this.calls[chain];
console.log(`\nFound ${calls.length} transactions for ${chain}`); console.log(`\nFound ${calls.length} transactions for ${chain}`);
const filterCalls = (submissionType: SubmissionType) => const filterCalls = (submissionType: SubmissionType) =>
@ -109,21 +108,19 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
} }
}; };
const connection = this.checker.multiProvider.getChainConnection(chain);
await sendCallsForType( await sendCallsForType(
SubmissionType.SIGNER, SubmissionType.SIGNER,
new SignerMultiSend(connection), new SignerMultiSend(this.checker.multiProvider, chain),
); );
const owner = this.checker.configMap[chain!].owner!; const owner = this.checker.configMap[chain!].owner!;
await sendCallsForType( await sendCallsForType(
SubmissionType.SAFE, SubmissionType.SAFE,
new SafeMultiSend(connection, chain, owner), new SafeMultiSend(this.checker.multiProvider, chain, owner),
); );
await sendCallsForType(SubmissionType.MANUAL, new ManualMultiSend(chain)); await sendCallsForType(SubmissionType.MANUAL, new ManualMultiSend(chain));
} }
protected pushCall(chain: Chain, call: AnnotatedCallData) { protected pushCall(chain: ChainName, call: AnnotatedCallData) {
this.calls[chain].push(call); this.calls[chain].push(call);
} }
@ -150,7 +147,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
handleProxyViolation(violation: ProxyViolation) { handleProxyViolation(violation: ProxyViolation) {
const contracts: CoreContracts = const contracts: CoreContracts =
this.checker.app.contractsMap[violation.chain as Chain]; this.checker.app.contractsMap[violation.chain];
let initData = '0x'; let initData = '0x';
switch (violation.data.name) { switch (violation.data.name) {
case 'InterchainGasPaymaster': case 'InterchainGasPaymaster':
@ -162,7 +159,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
default: default:
throw new Error(`Unsupported proxy violation ${violation.data.name}`); throw new Error(`Unsupported proxy violation ${violation.data.name}`);
} }
this.pushCall(violation.chain as Chain, { this.pushCall(violation.chain, {
to: contracts.proxyAdmin.address, to: contracts.proxyAdmin.address,
data: contracts.proxyAdmin.interface.encodeFunctionData( data: contracts.proxyAdmin.interface.encodeFunctionData(
'upgradeAndCall', 'upgradeAndCall',
@ -177,7 +174,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
} }
protected async inferCallSubmissionTypes() { protected async inferCallSubmissionTypes() {
for (const chain of Object.keys(this.calls) as Chain[]) { for (const chain of Object.keys(this.calls)) {
for (const call of this.calls[chain]) { for (const call of this.calls[chain]) {
const submissionType = await this.inferCallSubmissionType(chain, call); const submissionType = await this.inferCallSubmissionType(chain, call);
call.submissionType = submissionType; call.submissionType = submissionType;
@ -186,13 +183,13 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
} }
protected async inferCallSubmissionType( protected async inferCallSubmissionType(
chain: Chain, chain: ChainName,
call: AnnotatedCallData, call: AnnotatedCallData,
): Promise<SubmissionType> { ): Promise<SubmissionType> {
const connection = this.checker.multiProvider.getChainConnection(chain); const multiProvider = this.checker.multiProvider;
// 1. Check if the call will succeed with the default signer. // 1. Check if the call will succeed with the default signer.
try { try {
await connection.estimateGas(call); await multiProvider.estimateGas(chain, call);
return SubmissionType.SIGNER; return SubmissionType.SIGNER;
} catch (_) {} // eslint-disable-line no-empty } catch (_) {} // eslint-disable-line no-empty
@ -202,7 +199,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
// 2a. Confirm that the signer is a Safe owner or delegate. // 2a. Confirm that the signer is a Safe owner or delegate.
// This should implicitly check whether or not the owner is a gnosis // This should implicitly check whether or not the owner is a gnosis
// safe. // safe.
const signer = connection.signer; const signer = multiProvider.getSigner(chain);
if (!signer) throw new Error(`no signer found`); if (!signer) throw new Error(`no signer found`);
const signerAddress = await signer.getAddress(); const signerAddress = await signer.getAddress();
if (!this.canPropose[chain].has(safeAddress)) { if (!this.canPropose[chain].has(safeAddress)) {
@ -211,7 +208,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
await canProposeSafeTransactions( await canProposeSafeTransactions(
signerAddress, signerAddress,
chain, chain,
connection, multiProvider,
safeAddress, safeAddress,
), ),
); );
@ -220,7 +217,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
// 2b. Check if calling from the owner will succeed. // 2b. Check if calling from the owner will succeed.
if (this.canPropose[chain].get(safeAddress)) { if (this.canPropose[chain].get(safeAddress)) {
try { try {
await connection.provider.estimateGas({ await multiProvider.getProvider(chain).estimateGas({
...call, ...call,
from: safeAddress, from: safeAddress,
}); });
@ -242,21 +239,21 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
// add expected - actual elements // add expected - actual elements
utils utils
.difference(reconcile.expected, reconcile.actual) .difference(reconcile.expected, reconcile.actual)
.forEach((elem) => .forEach((elem) => this.pushCall(reconcile.chain, reconcile.add(elem)));
this.pushCall(reconcile.chain as Chain, reconcile.add(elem)),
);
// remote actual - expected elements // remote actual - expected elements
utils utils
.difference(reconcile.actual, reconcile.expected) .difference(reconcile.actual, reconcile.expected)
.forEach((elem) => .forEach((elem) =>
this.pushCall(reconcile.chain as Chain, reconcile.remove(elem)), this.pushCall(reconcile.chain, reconcile.remove(elem)),
); );
} }
handleMultisigIsmViolation(violation: MultisigIsmViolation) { handleMultisigIsmViolation(violation: MultisigIsmViolation) {
const multisigIsm = violation.contract; const multisigIsm = violation.contract;
const remoteDomainId = ChainNameToDomainId[violation.remote]; const remoteDomainId = this.checker.multiProvider.getDomainId(
violation.remote,
);
switch (violation.subType) { switch (violation.subType) {
case MultisigIsmViolationType.EnrolledValidators: { case MultisigIsmViolationType.EnrolledValidators: {
const baseDescription = `as ${violation.remote} validator on ${violation.chain}`; const baseDescription = `as ${violation.remote} validator on ${violation.chain}`;
@ -282,7 +279,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
break; break;
} }
case MultisigIsmViolationType.Threshold: { case MultisigIsmViolationType.Threshold: {
this.pushCall(violation.chain as Chain, { this.pushCall(violation.chain, {
to: multisigIsm.address, to: multisigIsm.address,
data: multisigIsm.interface.encodeFunctionData('setThreshold', [ data: multisigIsm.interface.encodeFunctionData('setThreshold', [
remoteDomainId, remoteDomainId,
@ -300,7 +297,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
} }
handleOwnerViolation(violation: OwnerViolation) { handleOwnerViolation(violation: OwnerViolation) {
this.pushCall(violation.chain as Chain, { this.pushCall(violation.chain, {
to: violation.contract.address, to: violation.contract.address,
data: violation.contract.interface.encodeFunctionData( data: violation.contract.interface.encodeFunctionData(
'transferOwnership', 'transferOwnership',

@ -1,4 +1,4 @@
import { ChainConnection, ChainName } from '@hyperlane-xyz/sdk'; import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk';
import { types } from '@hyperlane-xyz/utils'; import { types } from '@hyperlane-xyz/utils';
import { getSafe, getSafeService } from '../utils/safe'; import { getSafe, getSafeService } from '../utils/safe';
@ -8,16 +8,19 @@ export abstract class MultiSend {
} }
export class SignerMultiSend extends MultiSend { export class SignerMultiSend extends MultiSend {
readonly connection: ChainConnection; constructor(
public readonly multiProvider: MultiProvider,
constructor(connection: ChainConnection) { public readonly chain: ChainName,
) {
super(); super();
this.connection = connection;
} }
async sendTransactions(calls: types.CallData[]) { async sendTransactions(calls: types.CallData[]) {
for (const call of calls) { for (const call of calls) {
const receipt = await this.connection.sendTransaction(call); const receipt = await this.multiProvider.sendTransaction(
this.chain,
call,
);
console.log(`confirmed tx ${receipt.transactionHash}`); console.log(`confirmed tx ${receipt.transactionHash}`);
} }
} }
@ -38,23 +41,20 @@ export class ManualMultiSend extends MultiSend {
} }
export class SafeMultiSend extends MultiSend { export class SafeMultiSend extends MultiSend {
readonly connection: ChainConnection;
readonly chain: ChainName;
readonly safeAddress: string;
constructor( constructor(
connection: ChainConnection, public readonly multiProvider: MultiProvider,
chain: ChainName, public readonly chain: ChainName,
safeAddress: string, public readonly safeAddress: string,
) { ) {
super(); super();
this.connection = connection;
this.chain = chain;
this.safeAddress = safeAddress;
} }
async sendTransactions(calls: types.CallData[]) { async sendTransactions(calls: types.CallData[]) {
const safeSdk = await getSafe(this.connection, this.safeAddress); const safeSdk = await getSafe(
this.chain,
this.multiProvider,
this.safeAddress,
);
const safeTransactionData = calls.map((call) => { const safeTransactionData = calls.map((call) => {
return { to: call.to, data: call.data.toString(), value: '0' }; return { to: call.to, data: call.data.toString(), value: '0' };
}); });
@ -64,13 +64,13 @@ export class SafeMultiSend extends MultiSend {
const safeTxHash = await safeSdk.getTransactionHash(safeTransaction); const safeTxHash = await safeSdk.getTransactionHash(safeTransaction);
const senderSignature = await safeSdk.signTransactionHash(safeTxHash); const senderSignature = await safeSdk.signTransactionHash(safeTxHash);
const safeService = getSafeService(this.chain, this.connection); const safeService = getSafeService(this.chain, this.multiProvider);
if (!this.connection.signer) throw new Error('missing signer'); const senderAddress = await this.multiProvider.getSignerAddress(this.chain);
await safeService.proposeTransaction({ await safeService.proposeTransaction({
safeAddress: this.safeAddress, safeAddress: this.safeAddress,
safeTransactionData: safeTransaction.data, safeTransactionData: safeTransaction.data,
safeTxHash, safeTxHash,
senderAddress: await this.connection.signer.getAddress()!, senderAddress,
senderSignature: senderSignature.data, senderSignature: senderSignature.data,
}); });
} }

@ -18,22 +18,22 @@ type Contracts = {
const CREATE2FACTORYBYTECODE = const CREATE2FACTORYBYTECODE =
'0x608060405234801561001057600080fd5b50610640806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80634af63f0214610046578063c2b1041c14610082578063cf4d643214610095575b600080fd5b610059610054366004610486565b6100a8565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610059610090366004610514565b6100e7565b6100596100a336600461058a565b6101f4565b604080513360208201529081018290526000906100e09084906060015b604051602081830303815290604052805190602001206102c6565b9392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602082015290810182905260009081906060016040516020818303038152906040528051906020012090503081878760405161013f9291906105fa565b6040519081900381206101b49392916020017fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209695505050505050565b604080513360208201529081018490526000906102159086906060016100c5565b905060008173ffffffffffffffffffffffffffffffffffffffff1684846040516102409291906105fa565b6000604051808303816000865af19150503d806000811461027d576040519150601f19603f3d011682016040523d82523d6000602084013e610282565b606091505b50509050806102bd576040517f4f77232300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50949350505050565b60008251600003610303576040517f21744a5900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818351602085016000f5905073ffffffffffffffffffffffffffffffffffffffff811661035c576040517f4102e83a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251602084012060405173ffffffffffffffffffffffffffffffffffffffff83169184917f27b8e3132afa95254770e1c1d214eafde52bc47d1b6e1f5dfcbb380c3ca3f53290600090a492915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126103ec57600080fd5b813567ffffffffffffffff80821115610407576104076103ac565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561044d5761044d6103ac565b8160405283815286602085880101111561046657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561049957600080fd5b823567ffffffffffffffff8111156104b057600080fd5b6104bc858286016103db565b95602094909401359450505050565b60008083601f8401126104dd57600080fd5b50813567ffffffffffffffff8111156104f557600080fd5b60208301915083602082850101111561050d57600080fd5b9250929050565b6000806000806060858703121561052a57600080fd5b843567ffffffffffffffff81111561054157600080fd5b61054d878288016104cb565b909550935050602085013573ffffffffffffffffffffffffffffffffffffffff8116811461057a57600080fd5b9396929550929360400135925050565b600080600080606085870312156105a057600080fd5b843567ffffffffffffffff808211156105b857600080fd5b6105c4888389016103db565b95506020870135945060408701359150808211156105e157600080fd5b506105ee878288016104cb565b95989497509550505050565b818382376000910190815291905056fea2646970667358221220959b7947b895d33da4de69733c07a0543161262edcf0e8d1784935027b47462c64736f6c63430008110033'; '0x608060405234801561001057600080fd5b50610640806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80634af63f0214610046578063c2b1041c14610082578063cf4d643214610095575b600080fd5b610059610054366004610486565b6100a8565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610059610090366004610514565b6100e7565b6100596100a336600461058a565b6101f4565b604080513360208201529081018290526000906100e09084906060015b604051602081830303815290604052805190602001206102c6565b9392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602082015290810182905260009081906060016040516020818303038152906040528051906020012090503081878760405161013f9291906105fa565b6040519081900381206101b49392916020017fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209695505050505050565b604080513360208201529081018490526000906102159086906060016100c5565b905060008173ffffffffffffffffffffffffffffffffffffffff1684846040516102409291906105fa565b6000604051808303816000865af19150503d806000811461027d576040519150601f19603f3d011682016040523d82523d6000602084013e610282565b606091505b50509050806102bd576040517f4f77232300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50949350505050565b60008251600003610303576040517f21744a5900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818351602085016000f5905073ffffffffffffffffffffffffffffffffffffffff811661035c576040517f4102e83a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251602084012060405173ffffffffffffffffffffffffffffffffffffffff83169184917f27b8e3132afa95254770e1c1d214eafde52bc47d1b6e1f5dfcbb380c3ca3f53290600090a492915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126103ec57600080fd5b813567ffffffffffffffff80821115610407576104076103ac565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561044d5761044d6103ac565b8160405283815286602085880101111561046657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561049957600080fd5b823567ffffffffffffffff8111156104b057600080fd5b6104bc858286016103db565b95602094909401359450505050565b60008083601f8401126104dd57600080fd5b50813567ffffffffffffffff8111156104f557600080fd5b60208301915083602082850101111561050d57600080fd5b9250929050565b6000806000806060858703121561052a57600080fd5b843567ffffffffffffffff81111561054157600080fd5b61054d878288016104cb565b909550935050602085013573ffffffffffffffffffffffffffffffffffffffff8116811461057a57600080fd5b9396929550929360400135925050565b600080600080606085870312156105a057600080fd5b843567ffffffffffffffff808211156105b857600080fd5b6105c4888389016103db565b95506020870135945060408701359150808211156105e157600080fd5b506105ee878288016104cb565b95989497509550505050565b818382376000910190815291905056fea2646970667358221220959b7947b895d33da4de69733c07a0543161262edcf0e8d1784935027b47462c64736f6c63430008110033';
export class Create2FactoryDeployer< export class Create2FactoryDeployer extends HyperlaneDeployer<
Chain extends ChainName, any,
> extends HyperlaneDeployer<Chain, any, Contracts, typeof factories> { Contracts,
constructor(multiProvider: MultiProvider<Chain>) { typeof factories
> {
constructor(multiProvider: MultiProvider) {
super( super(
multiProvider, multiProvider,
multiProvider.map(() => ({})), multiProvider.mapKnownChains(() => ({})),
factories, factories,
); );
} }
async deployContracts(chain: Chain) { async deployContracts(chain: ChainName) {
const chainConnection = this.multiProvider.getChainConnection(chain); const provider = this.multiProvider.getProvider(chain);
const signer = this.multiProvider.getChainSigner(chain); const signer = this.multiProvider.getSigner(chain);
if ( if ((await provider.getCode(CREATE2FACTORY_ADDRESS)) === '0x') {
(await chainConnection.provider.getCode(CREATE2FACTORY_ADDRESS)) === '0x'
) {
const tx = await signer.signTransaction({ const tx = await signer.signTransaction({
data: CREATE2FACTORYBYTECODE, data: CREATE2FACTORYBYTECODE,
chainId: 0, chainId: 0,
@ -43,9 +43,7 @@ export class Create2FactoryDeployer<
nonce: 0, nonce: 0,
}); });
await chainConnection.handleTx( await this.multiProvider.handleTx(chain, provider.sendTransaction(tx));
chainConnection.provider.sendTransaction(tx),
);
} }
const Create2Factory = Create2Factory__factory.connect( const Create2Factory = Create2Factory__factory.connect(

@ -12,9 +12,9 @@ import { readJSON, writeJSON } from './utils/utils';
export async function deployWithArtifacts<T extends HyperlaneFactories>( export async function deployWithArtifacts<T extends HyperlaneFactories>(
dir: string, dir: string,
factories: T, factories: T,
deployer: HyperlaneDeployer<any, any, any, T>, deployer: HyperlaneDeployer<any, any, T>,
) { ) {
let contracts: ChainMap<any, HyperlaneContracts> = {}; let contracts: ChainMap<HyperlaneContracts> = {};
try { try {
const addresses = readJSON(dir, 'addresses.json'); const addresses = readJSON(dir, 'addresses.json');
contracts = buildContracts(addresses, factories) as any; contracts = buildContracts(addresses, factories) as any;

@ -1,13 +1,11 @@
import { ChainName } from '@hyperlane-xyz/sdk';
import { AgentConfig, CoreEnvironmentConfig } from '../config'; import { AgentConfig, CoreEnvironmentConfig } from '../config';
import { KeyFunderConfig } from '../config/funding'; import { KeyFunderConfig } from '../config/funding';
import { HelmCommand, helmifyValues } from '../utils/helm'; import { HelmCommand, helmifyValues } from '../utils/helm';
import { execCmd } from '../utils/utils'; import { execCmd } from '../utils/utils';
export async function runKeyFunderHelmCommand<Chain extends ChainName>( export async function runKeyFunderHelmCommand(
helmCommand: HelmCommand, helmCommand: HelmCommand,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
keyFunderConfig: KeyFunderConfig, keyFunderConfig: KeyFunderConfig,
) { ) {
const values = getKeyFunderHelmValues(agentConfig, keyFunderConfig); const values = getKeyFunderHelmValues(agentConfig, keyFunderConfig);
@ -36,8 +34,8 @@ export async function runKeyFunderHelmCommand<Chain extends ChainName>(
); );
} }
function getKeyFunderHelmValues<Chain extends ChainName>( function getKeyFunderHelmValues(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
keyFunderConfig: KeyFunderConfig, keyFunderConfig: KeyFunderConfig,
) { ) {
const values = { const values = {
@ -64,7 +62,7 @@ function getKeyFunderHelmValues<Chain extends ChainName>(
} }
export function getKeyFunderConfig( export function getKeyFunderConfig(
coreConfig: CoreEnvironmentConfig<any>, coreConfig: CoreEnvironmentConfig,
): KeyFunderConfig { ): KeyFunderConfig {
const keyFunderConfig = coreConfig.keyFunderConfig; const keyFunderConfig = coreConfig.keyFunderConfig;
if (!keyFunderConfig) { if (!keyFunderConfig) {

@ -1,5 +1,3 @@
import { ChainName } from '@hyperlane-xyz/sdk';
import { Contexts } from '../../config/contexts'; import { Contexts } from '../../config/contexts';
import { AgentAwsUser } from '../agents/aws'; import { AgentAwsUser } from '../agents/aws';
import { KEY_ROLE_ENUM } from '../agents/roles'; import { KEY_ROLE_ENUM } from '../agents/roles';
@ -11,14 +9,14 @@ import {
import { HelmCommand, helmifyValues } from '../utils/helm'; import { HelmCommand, helmifyValues } from '../utils/helm';
import { execCmd } from '../utils/utils'; import { execCmd } from '../utils/utils';
export async function runHelloworldKathyHelmCommand<Chain extends ChainName>( export async function runHelloworldKathyHelmCommand(
helmCommand: HelmCommand, helmCommand: HelmCommand,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
kathyConfig: HelloWorldKathyConfig<Chain>, kathyConfig: HelloWorldKathyConfig,
) { ) {
// If using AWS keys, ensure the Kathy user and key has been created // If using AWS keys, ensure the Kathy user and key has been created
if (agentConfig.aws) { if (agentConfig.aws) {
const awsUser = new AgentAwsUser<Chain>( const awsUser = new AgentAwsUser(
agentConfig.environment, agentConfig.environment,
agentConfig.context, agentConfig.context,
KEY_ROLE_ENUM.Kathy, KEY_ROLE_ENUM.Kathy,
@ -50,9 +48,9 @@ function getHelmReleaseName(context: Contexts): string {
}`; }`;
} }
function getHelloworldKathyHelmValues<Chain extends ChainName>( function getHelloworldKathyHelmValues(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
kathyConfig: HelloWorldKathyConfig<Chain>, kathyConfig: HelloWorldKathyConfig,
) { ) {
const cycleOnce = const cycleOnce =
kathyConfig.runConfig.mode === HelloWorldKathyRunMode.CycleOnce; kathyConfig.runConfig.mode === HelloWorldKathyRunMode.CycleOnce;

@ -1,15 +1,11 @@
import { ChainName } from '@hyperlane-xyz/sdk';
import { AgentConfig, CoreEnvironmentConfig } from '../config'; import { AgentConfig, CoreEnvironmentConfig } from '../config';
import { LiquidityLayerRelayerConfig } from '../config/middleware'; import { LiquidityLayerRelayerConfig } from '../config/middleware';
import { HelmCommand, helmifyValues } from '../utils/helm'; import { HelmCommand, helmifyValues } from '../utils/helm';
import { execCmd } from '../utils/utils'; import { execCmd } from '../utils/utils';
export async function runLiquidityLayerRelayerHelmCommand< export async function runLiquidityLayerRelayerHelmCommand(
Chain extends ChainName,
>(
helmCommand: HelmCommand, helmCommand: HelmCommand,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
relayerConfig: LiquidityLayerRelayerConfig, relayerConfig: LiquidityLayerRelayerConfig,
) { ) {
const values = getLiquidityLayerRelayerHelmValues(agentConfig, relayerConfig); const values = getLiquidityLayerRelayerHelmValues(agentConfig, relayerConfig);
@ -38,8 +34,8 @@ export async function runLiquidityLayerRelayerHelmCommand<
); );
} }
function getLiquidityLayerRelayerHelmValues<Chain extends ChainName>( function getLiquidityLayerRelayerHelmValues(
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
relayerConfig: LiquidityLayerRelayerConfig, relayerConfig: LiquidityLayerRelayerConfig,
) { ) {
const values = { const values = {
@ -61,7 +57,7 @@ function getLiquidityLayerRelayerHelmValues<Chain extends ChainName>(
} }
export function getLiquidityLayerRelayerConfig( export function getLiquidityLayerRelayerConfig(
coreConfig: CoreEnvironmentConfig<any>, coreConfig: CoreEnvironmentConfig,
): LiquidityLayerRelayerConfig { ): LiquidityLayerRelayerConfig {
const relayerConfig = coreConfig.liquidityLayerRelayerConfig; const relayerConfig = coreConfig.liquidityLayerRelayerConfig;
if (!relayerConfig) { if (!relayerConfig) {

@ -1,5 +1,3 @@
import { ChainName } from '@hyperlane-xyz/sdk';
import { AgentConfig } from '../config'; import { AgentConfig } from '../config';
import { ConnectionType } from '../config/agent'; import { ConnectionType } from '../config/agent';
import { import {
@ -11,9 +9,9 @@ import { execCmd } from '../utils/utils';
const helmChartPath = '../../rust/helm/hyperlane-agent/'; const helmChartPath = '../../rust/helm/hyperlane-agent/';
export async function runScraperHelmCommand<Chain extends ChainName>( export async function runScraperHelmCommand(
action: HelmCommand, action: HelmCommand,
agentConfig: AgentConfig<Chain>, agentConfig: AgentConfig,
) { ) {
const values = await scraperHelmValues(agentConfig); const values = await scraperHelmValues(agentConfig);
@ -51,9 +49,7 @@ export async function runScraperHelmCommand<Chain extends ChainName>(
); );
} }
async function scraperHelmValues<Chain extends ChainName>( async function scraperHelmValues(agentConfig: AgentConfig) {
agentConfig: AgentConfig<Chain>,
) {
// By default, if a context only enables a subset of chains, the // By default, if a context only enables a subset of chains, the
// connection url (or urls, when HttpQuorum is used) are not fetched // connection url (or urls, when HttpQuorum is used) are not fetched
// from GCP secret manager. For Http/Ws, the `url` param is expected, // from GCP secret manager. For Http/Ws, the `url` param is expected,

@ -17,22 +17,19 @@ type Contracts = {
TestQuerySender: TestQuerySender; TestQuerySender: TestQuerySender;
}; };
export class TestQuerySenderDeployer< export class TestQuerySenderDeployer extends HyperlaneDeployer<
Chain extends ChainName,
> extends HyperlaneDeployer<
Chain,
TestQuerySenderConfig, TestQuerySenderConfig,
Contracts, Contracts,
typeof factories typeof factories
> { > {
constructor( constructor(
multiProvider: MultiProvider<Chain>, multiProvider: MultiProvider,
queryRouters: ChainMap<Chain, TestQuerySenderConfig>, queryRouters: ChainMap<TestQuerySenderConfig>,
protected core: HyperlaneCore<Chain>, protected core: HyperlaneCore,
) { ) {
super(multiProvider, queryRouters, factories); super(multiProvider, queryRouters, factories);
} }
async deployContracts(chain: Chain, config: TestQuerySenderConfig) { async deployContracts(chain: ChainName, config: TestQuerySenderConfig) {
const initCalldata = const initCalldata =
TestQuerySender__factory.createInterface().encodeFunctionData( TestQuerySender__factory.createInterface().encodeFunctionData(
'initialize', 'initialize',

@ -20,17 +20,19 @@ type Contracts = {
TestTokenRecipient: TestTokenRecipient; TestTokenRecipient: TestTokenRecipient;
}; };
export class TestRecipientDeployer< export class TestRecipientDeployer extends HyperlaneDeployer<
Chain extends ChainName, any,
> extends HyperlaneDeployer<Chain, any, Contracts, typeof factories> { Contracts,
constructor(multiProvider: MultiProvider<Chain>) { typeof factories
> {
constructor(multiProvider: MultiProvider) {
super( super(
multiProvider, multiProvider,
multiProvider.map(() => ({})), multiProvider.mapKnownChains(() => ({})),
factories, factories,
); );
} }
async deployContracts(chain: Chain) { async deployContracts(chain: ChainName) {
const TestRecipient = await this.deployContract( const TestRecipient = await this.deployContract(
chain, chain,
'TestRecipient', 'TestRecipient',

@ -3,14 +3,13 @@ import EthersAdapter from '@safe-global/safe-ethers-lib';
import SafeServiceClient from '@safe-global/safe-service-client'; import SafeServiceClient from '@safe-global/safe-service-client';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { ChainConnection, ChainName, chainMetadata } from '@hyperlane-xyz/sdk'; import { ChainName, MultiProvider, chainMetadata } from '@hyperlane-xyz/sdk';
export function getSafeService( export function getSafeService(
chain: ChainName, chain: ChainName,
connection: ChainConnection, multiProvider: MultiProvider,
): SafeServiceClient { ): SafeServiceClient {
const signer = connection.signer; const signer = multiProvider.getSigner(chain);
if (!signer) throw new Error(`no signer found for ${chain}`);
const ethAdapter = new EthersAdapter({ ethers, signerOrProvider: signer }); const ethAdapter = new EthersAdapter({ ethers, signerOrProvider: signer });
const txServiceUrl = chainMetadata[chain].gnosisSafeTransactionServiceUrl; const txServiceUrl = chainMetadata[chain].gnosisSafeTransactionServiceUrl;
if (!txServiceUrl) if (!txServiceUrl)
@ -19,11 +18,11 @@ export function getSafeService(
} }
export function getSafe( export function getSafe(
connection: ChainConnection, chain: ChainName,
multiProvider: MultiProvider,
safeAddress: string, safeAddress: string,
): Promise<Safe> { ): Promise<Safe> {
const signer = connection.signer; const signer = multiProvider.getSigner(chain);
if (!signer) throw new Error(`no signer found`);
const ethAdapter = new EthersAdapter({ ethers, signerOrProvider: signer }); const ethAdapter = new EthersAdapter({ ethers, signerOrProvider: signer });
return Safe.create({ return Safe.create({
ethAdapter, ethAdapter,
@ -42,11 +41,11 @@ export async function getSafeDelegates(
export async function canProposeSafeTransactions( export async function canProposeSafeTransactions(
proposer: string, proposer: string,
chain: ChainName, chain: ChainName,
connection: ChainConnection, multiProvider: MultiProvider,
safeAddress: string, safeAddress: string,
): Promise<boolean> { ): Promise<boolean> {
const safeService = getSafeService(chain, connection); const safeService = getSafeService(chain, multiProvider);
const safe = await getSafe(connection, safeAddress); const safe = await getSafe(chain, multiProvider, safeAddress);
const delegates = await getSafeDelegates(safeService, safeAddress); const delegates = await getSafeDelegates(safeService, safeAddress);
const owners = await safe.getOwners(); const owners = await safe.getOwners();
return delegates.includes(proposer) || owners.includes(proposer); return delegates.includes(proposer) || owners.includes(proposer);

@ -5,7 +5,7 @@ import { ethers } from 'ethers';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { AllChains, ChainName } from '@hyperlane-xyz/sdk'; import { AllChains, ChainName, CoreChainName } from '@hyperlane-xyz/sdk';
import { Contexts } from '../../config/contexts'; import { Contexts } from '../../config/contexts';
import { ALL_KEY_ROLES, KEY_ROLE_ENUM } from '../agents/roles'; import { ALL_KEY_ROLES, KEY_ROLE_ENUM } from '../agents/roles';
@ -187,7 +187,7 @@ export function assertRole(roleStr: string) {
export function assertChain(chainStr: string) { export function assertChain(chainStr: string) {
const chain = chainStr as ChainName; const chain = chainStr as ChainName;
if (!AllChains.includes(chain)) { if (!AllChains.includes(chain as CoreChainName)) {
throw Error(`Invalid chain ${chain}`); throw Error(`Invalid chain ${chain}`);
} }
return chain; return chain;

@ -10,32 +10,30 @@ import {
HyperlaneCore, HyperlaneCore,
HyperlaneCoreChecker, HyperlaneCoreChecker,
MultiProvider, MultiProvider,
getTestMultiProvider,
objMap, objMap,
serializeContracts, serializeContracts,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { environment as testConfig } from '../config/environments/test'; import { environment as testConfig } from '../config/environments/test';
import { TestChains } from '../config/environments/test/chains';
import { HyperlaneCoreInfraDeployer } from '../src/core/deploy'; import { HyperlaneCoreInfraDeployer } from '../src/core/deploy';
import { writeJSON } from '../src/utils/utils'; import { writeJSON } from '../src/utils/utils';
describe('core', async () => { describe('core', async () => {
const environment = 'test'; const environment = 'test';
let multiProvider: MultiProvider<TestChains>; let multiProvider: MultiProvider;
let deployer: HyperlaneCoreInfraDeployer<TestChains>; let deployer: HyperlaneCoreInfraDeployer;
let core: HyperlaneCore<TestChains>; let core: HyperlaneCore;
let contracts: CoreContractsMap<TestChains>; let contracts: CoreContractsMap;
let coreConfig: ChainMap<TestChains, CoreConfig>; let coreConfig: ChainMap<CoreConfig>;
let owners: ChainMap<TestChains, string>; let owners: ChainMap<string>;
beforeEach(async () => { beforeEach(async () => {
const [signer, owner] = await ethers.getSigners(); const [signer, owner] = await ethers.getSigners();
// This is kind of awkward and really these tests shouldn't live here // This is kind of awkward and really these tests shouldn't live here
multiProvider = getTestMultiProvider(signer, testConfig.transactionConfigs); multiProvider = MultiProvider.createTestMultiProvider({ signer });
coreConfig = testConfig.core; coreConfig = testConfig.core;
owners = objMap(testConfig.transactionConfigs, () => owner.address); owners = objMap(testConfig.chainMetadataConfigs, () => owner.address);
}); });
it('deploys', async () => { it('deploys', async () => {
@ -91,7 +89,9 @@ describe('core', async () => {
it('can be resumed from partial contracts', async () => { it('can be resumed from partial contracts', async () => {
sinon.restore(); // restore normal deployer behavior sinon.restore(); // restore normal deployer behavior
//@ts-ignore operand not optional, ignore for this test
delete deployer.deployedContracts.test2!.multisigIsm; delete deployer.deployedContracts.test2!.multisigIsm;
//@ts-ignore operand not optional, ignore for this test
delete deployer.deployedContracts.test2!.mailbox; delete deployer.deployedContracts.test2!.mailbox;
const result = await deployer.deploy(); const result = await deployer.deploy();

@ -3970,11 +3970,11 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@hyperlane-xyz/helloworld@1.1.4, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": "@hyperlane-xyz/helloworld@1.2.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld"
dependencies: dependencies:
"@hyperlane-xyz/sdk": 1.1.4 "@hyperlane-xyz/sdk": 1.2.0
"@nomiclabs/hardhat-ethers": ^2.2.1 "@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3 "@nomiclabs/hardhat-waffle": ^2.0.3
"@openzeppelin/contracts-upgradeable": ^4.8.0 "@openzeppelin/contracts-upgradeable": ^4.8.0
@ -4051,10 +4051,9 @@ __metadata:
"@gnosis.pm/safe-core-sdk": ^2.3.2 "@gnosis.pm/safe-core-sdk": ^2.3.2
"@gnosis.pm/safe-ethers-lib": ^1.4.0 "@gnosis.pm/safe-ethers-lib": ^1.4.0
"@gnosis.pm/safe-service-client": ^1.2.0 "@gnosis.pm/safe-service-client": ^1.2.0
"@hyperlane-xyz/celo-ethers-provider": ^0.1.1 "@hyperlane-xyz/helloworld": 1.2.0
"@hyperlane-xyz/helloworld": 1.1.4 "@hyperlane-xyz/sdk": 1.2.0
"@hyperlane-xyz/sdk": 1.1.4 "@hyperlane-xyz/utils": 1.2.0
"@hyperlane-xyz/utils": 1.1.4
"@nomiclabs/hardhat-ethers": ^2.2.1 "@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-etherscan": ^3.0.3 "@nomiclabs/hardhat-etherscan": ^3.0.3
"@nomiclabs/hardhat-waffle": ^2.0.3 "@nomiclabs/hardhat-waffle": ^2.0.3
@ -4097,23 +4096,7 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@hyperlane-xyz/sdk@npm:1.1.4": "@hyperlane-xyz/sdk@1.2.0, @hyperlane-xyz/sdk@workspace:typescript/sdk":
version: 1.1.4
resolution: "@hyperlane-xyz/sdk@npm:1.1.4"
dependencies:
"@hyperlane-xyz/celo-ethers-provider": ^0.1.1
"@hyperlane-xyz/core": 1.1.4
"@hyperlane-xyz/utils": 1.1.4
"@wagmi/chains": ^0.2.6
coingecko-api: ^1.0.10
cross-fetch: ^3.1.5
debug: ^4.3.4
ethers: ^5.7.2
checksum: 600d81648cdbdad2be4200bd772d49128b9bcd5de10d1f811008291ed268610a0bb1cac8061dfa30b5040dc20c7b8919b39ed206d7993f63c65abf3df663c125
languageName: node
linkType: hard
"@hyperlane-xyz/sdk@workspace:typescript/sdk":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk"
dependencies: dependencies:
@ -4142,6 +4125,22 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@hyperlane-xyz/sdk@npm:1.1.4":
version: 1.1.4
resolution: "@hyperlane-xyz/sdk@npm:1.1.4"
dependencies:
"@hyperlane-xyz/celo-ethers-provider": ^0.1.1
"@hyperlane-xyz/core": 1.1.4
"@hyperlane-xyz/utils": 1.1.4
"@wagmi/chains": ^0.2.6
coingecko-api: ^1.0.10
cross-fetch: ^3.1.5
debug: ^4.3.4
ethers: ^5.7.2
checksum: 600d81648cdbdad2be4200bd772d49128b9bcd5de10d1f811008291ed268610a0bb1cac8061dfa30b5040dc20c7b8919b39ed206d7993f63c65abf3df663c125
languageName: node
linkType: hard
"@hyperlane-xyz/utils@1.2.0, @hyperlane-xyz/utils@workspace:typescript/utils": "@hyperlane-xyz/utils@1.2.0, @hyperlane-xyz/utils@workspace:typescript/utils":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" resolution: "@hyperlane-xyz/utils@workspace:typescript/utils"

Loading…
Cancel
Save