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 { helloworldMatchingList, routerMatchingList } from '../../utils';
import { MainnetChains, chainNames, environment } from './chains';
import { chainNames, environment } from './chains';
import { helloWorld } from './helloworld';
import interchainQueryRouters from './middleware/queries/addresses.json';
import { validators } from './validators';
@ -23,7 +23,7 @@ const interchainQueriesMatchingList = routerMatchingList(
interchainQueryRouters,
);
export const hyperlane: AgentConfig<MainnetChains> = {
export const hyperlane: AgentConfig = {
environment,
namespace: environment,
runEnv: environment,
@ -67,7 +67,7 @@ export const hyperlane: AgentConfig<MainnetChains> = {
rolesWithKeys: ALL_KEY_ROLES,
};
export const releaseCandidate: AgentConfig<MainnetChains> = {
export const releaseCandidate: AgentConfig = {
environment,
namespace: environment,
runEnv: environment,
@ -98,7 +98,7 @@ export const releaseCandidate: AgentConfig<MainnetChains> = {
transactionGasLimit: BigInt(750000),
// Skipping arbitrum because the gas price estimates are inclusive of L1
// fees which leads to wildly off predictions.
skipTransactionGasLimitFor: [chainMetadata.arbitrum.id],
skipTransactionGasLimitFor: [chainMetadata.arbitrum.chainId],
},
},
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: {
...chainConnectionConfigs.bsc,
overrides: {
...chainMetadata.bsc,
transactionOverrides: {
gasPrice: 7 * 10 ** 9, // 7 gwei
},
},
avalanche: chainConnectionConfigs.avalanche,
avalanche: chainMetadata.avalanche,
polygon: {
...chainConnectionConfigs.polygon,
confirmations: 3,
overrides: {
...chainMetadata.polygon,
blocks: {
...chainMetadata.polygon.blocks,
confirmations: 3,
},
transactionOverrides: {
maxFeePerGas: 500 * 10 ** 9, // 500 gwei
maxPriorityFeePerGas: 100 * 10 ** 9, // 100 gwei
// gasPrice: 50 * 10 ** 9, // 50 gwei
},
},
celo: chainConnectionConfigs.celo,
arbitrum: chainConnectionConfigs.arbitrum,
optimism: chainConnectionConfigs.optimism,
celo: chainMetadata.celo,
arbitrum: chainMetadata.arbitrum,
optimism: chainMetadata.optimism,
ethereum: {
...chainConnectionConfigs.ethereum,
confirmations: 3,
overrides: {
...chainMetadata.ethereum,
blocks: {
...chainMetadata.ethereum.blocks,
confirmations: 3,
},
transactionOverrides: {
maxFeePerGas: 150 * 10 ** 9, // gwei
maxPriorityFeePerGas: 5 * 10 ** 9, // gwei
},
},
moonbeam: chainConnectionConfigs.moonbeam,
gnosis: chainConnectionConfigs.gnosis,
moonbeam: chainMetadata.moonbeam,
gnosis: chainMetadata.gnosis,
};
export type MainnetChains = keyof typeof mainnetConfigs;

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

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

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

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

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

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

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

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

@ -1,24 +1,26 @@
import { JsonRpcProvider } from '@ethersproject/providers';
import { getTestMultiProvider } from '@hyperlane-xyz/sdk';
import { MultiProvider } from '@hyperlane-xyz/sdk';
import { CoreEnvironmentConfig } from '../../../src/config';
import { agents } from './agent';
import { TestChains, testConfigs } from './chains';
import { testConfigs } from './chains';
import { core } from './core';
import { infra } from './infra';
export const environment: CoreEnvironmentConfig<TestChains> = {
export const environment: CoreEnvironmentConfig = {
environment: 'test',
transactionConfigs: testConfigs,
chainMetadataConfigs: testConfigs,
agents,
core,
infra,
// NOTE: Does not work from hardhat.config.ts
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);
return getTestMultiProvider(signer, testConfigs);
mp.setSharedSigner(signer);
return mp;
},
};

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

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

@ -9,7 +9,7 @@ import {
import { Contexts } from '../../contexts';
import { helloworldMatchingList, routerMatchingList } from '../../utils';
import { TestnetChains, chainNames, environment } from './chains';
import { chainNames, environment } from './chains';
import { helloWorld } from './helloworld';
import interchainQueryRouters from './middleware/queries/addresses.json';
import { validators } from './validators';
@ -23,7 +23,7 @@ const interchainQueriesMatchingList = routerMatchingList(
interchainQueryRouters,
);
export const hyperlane: AgentConfig<TestnetChains> = {
export const hyperlane: AgentConfig = {
environment,
namespace: environment,
runEnv: environment,
@ -64,7 +64,7 @@ export const hyperlane: AgentConfig<TestnetChains> = {
rolesWithKeys: ALL_KEY_ROLES,
};
export const releaseCandidate: AgentConfig<TestnetChains> = {
export const releaseCandidate: AgentConfig = {
environment,
namespace: environment,
runEnv: environment,
@ -95,7 +95,7 @@ export const releaseCandidate: AgentConfig<TestnetChains> = {
transactionGasLimit: BigInt(750000),
// Skipping arbitrum because the gas price estimates are inclusive of L1
// fees which leads to wildly off predictions.
skipTransactionGasLimitFor: [chainMetadata.arbitrumgoerli.id],
skipTransactionGasLimitFor: [chainMetadata.arbitrumgoerli.chainId],
},
},
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 = {
alfajores: chainConnectionConfigs.alfajores,
fuji: chainConnectionConfigs.fuji,
export const testnetConfigs: ChainMap<ChainMetadata> = {
alfajores: chainMetadata.alfajores,
fuji: chainMetadata.fuji,
mumbai: {
...chainConnectionConfigs.mumbai,
overrides: {
...chainMetadata.mumbai,
transactionOverrides: {
maxFeePerGas: 70 * 10 ** 9, // 70 gwei
maxPriorityFeePerGas: 40 * 10 ** 9, // 40 gwei
},
},
bsctestnet: chainConnectionConfigs.bsctestnet,
goerli: chainConnectionConfigs.goerli,
moonbasealpha: chainConnectionConfigs.moonbasealpha,
optimismgoerli: chainConnectionConfigs.optimismgoerli,
arbitrumgoerli: chainConnectionConfigs.arbitrumgoerli,
bsctestnet: chainMetadata.bsctestnet,
goerli: chainMetadata.goerli,
moonbasealpha: chainMetadata.moonbasealpha,
optimismgoerli: chainMetadata.optimismgoerli,
arbitrumgoerli: chainMetadata.arbitrumgoerli,
};
export type TestnetChains = keyof typeof testnetConfigs;

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

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

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

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

@ -1,23 +1,21 @@
import { ChainName, chainMetadata } from '@hyperlane-xyz/sdk';
import { CoreChainName, chainMetadata } from '@hyperlane-xyz/sdk';
import {
ChainValidatorConfigs,
CheckpointSyncerType,
} from '../../../src/config/agent';
import { TestnetChains, environment } from './chains';
import { environment } from './chains';
const s3BucketRegion = 'us-east-1';
const s3BucketName = <Chain extends ChainName>(
chainName: Chain,
index: number,
) => `hyperlane-${environment}-${chainName}-validator-${index}`;
const s3BucketName = (chainName: CoreChainName, index: number) =>
`hyperlane-${environment}-${chainName}-validator-${index}`;
export const validators: ChainValidatorConfigs<TestnetChains> = {
export const validators: ChainValidatorConfigs = {
alfajores: {
interval: 5,
reorgPeriod: chainMetadata.alfajores.blocks.reorgPeriod,
reorgPeriod: chainMetadata.alfajores.blocks!.reorgPeriod!,
validators: [
{
address: '0xe6072396568e73ce6803b12b7e04164e839f1e54',
@ -50,7 +48,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
fuji: {
interval: 5,
reorgPeriod: chainMetadata.fuji.blocks.reorgPeriod,
reorgPeriod: chainMetadata.fuji.blocks!.reorgPeriod!,
validators: [
{
address: '0x9fa19ead5ec76e437948b35e227511b106293c40',
@ -83,7 +81,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
mumbai: {
interval: 5,
reorgPeriod: chainMetadata.mumbai.blocks.reorgPeriod,
reorgPeriod: chainMetadata.mumbai.blocks!.reorgPeriod!,
validators: [
{
address: '0x0a664ea799447da6b15645cf8b9e82072a68343f',
@ -116,7 +114,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
bsctestnet: {
interval: 5,
reorgPeriod: chainMetadata.bsctestnet.blocks.reorgPeriod,
reorgPeriod: chainMetadata.bsctestnet.blocks!.reorgPeriod!,
validators: [
{
address: '0x23338c8714976dd4a57eaeff17cbd26d7e275c08',
@ -149,7 +147,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
goerli: {
interval: 5,
reorgPeriod: chainMetadata.goerli.blocks.reorgPeriod,
reorgPeriod: chainMetadata.goerli.blocks!.reorgPeriod!,
validators: [
{
address: '0xf43fbd072fd38e1121d4b3b0b8a35116bbb01ea9',
@ -182,7 +180,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
moonbasealpha: {
interval: 5,
reorgPeriod: chainMetadata.moonbasealpha.blocks.reorgPeriod,
reorgPeriod: chainMetadata.moonbasealpha.blocks!.reorgPeriod!,
validators: [
{
address: '0x890c2aeac157c3f067f3e42b8afc797939c59a32',
@ -215,7 +213,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
optimismgoerli: {
interval: 5,
reorgPeriod: chainMetadata.optimismgoerli.blocks.reorgPeriod,
reorgPeriod: chainMetadata.optimismgoerli.blocks!.reorgPeriod!,
validators: [
{
address: '0xbb8d77eefbecc55db6e5a19b0fc3dc290776f189',
@ -248,7 +246,7 @@ export const validators: ChainValidatorConfigs<TestnetChains> = {
},
arbitrumgoerli: {
interval: 5,
reorgPeriod: chainMetadata.arbitrumgoerli.blocks.reorgPeriod,
reorgPeriod: chainMetadata.arbitrumgoerli.blocks!.reorgPeriod!,
validators: [
{
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 { MatchingList } from '../src/config/agent';
@ -14,8 +14,8 @@ export const MATCHING_LIST_ALL_WILDCARDS = [
},
];
export function helloworldMatchingList<Chain extends ChainName>(
helloWorldConfigs: Partial<Record<Contexts, HelloWorldConfig<Chain>>>,
export function helloworldMatchingList(
helloWorldConfigs: Partial<Record<Contexts, HelloWorldConfig>>,
context: Contexts,
) {
const helloWorldConfig = helloWorldConfigs[context];
@ -25,10 +25,8 @@ export function helloworldMatchingList<Chain extends ChainName>(
return routerMatchingList(helloWorldConfig.addresses);
}
export function routerMatchingList<Chain extends ChainName>(
routers: ChainMap<Chain, { router: string }>,
) {
const chains = Object.keys(routers) as Chain[];
export function routerMatchingList(routers: ChainMap<{ router: string }>) {
const chains = Object.keys(routers);
const matchingList: MatchingList = [];
@ -39,9 +37,9 @@ export function routerMatchingList<Chain extends ChainName>(
}
matchingList.push({
originDomain: chainMetadata[source].id,
originDomain: chainMetadata[source].chainId,
senderAddress: routers[source].router,
destinationDomain: chainMetadata[destination].id,
destinationDomain: chainMetadata[destination].chainId,
recipientAddress: routers[destination].router,
});
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -33,9 +33,8 @@ async function delegate() {
const { chain, delegate, safe, action } = await getArgs();
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);
console.log('Connecting to ledger, ensure plugged in and unlocked...');

@ -17,7 +17,7 @@ async function deploy() {
const agentConfig = await getContextAgentConfig(config);
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 {
AllChains,
ChainMap,
ChainMetadata,
ChainName,
IChainConnection,
MultiProvider,
objMap,
promiseObjAll,
@ -55,7 +55,7 @@ export function assertEnvironment(env: string): DeployEnvironment {
export function getCoreEnvironmentConfig<Env extends DeployEnvironment>(
env: Env,
): CoreEnvironmentConfig<any> {
): CoreEnvironmentConfig {
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.
export async function getContextAgentConfig<Chain extends ChainName>(
coreEnvironmentConfig?: CoreEnvironmentConfig<Chain>,
export async function getContextAgentConfig(
coreEnvironmentConfig?: CoreEnvironmentConfig,
defaultContext?: string,
) {
return getAgentConfig(
@ -85,9 +85,9 @@ export async function getContextAgentConfig<Chain extends ChainName>(
}
// Gets the agent config of a specific context.
export async function getAgentConfig<Chain extends ChainName>(
export async function getAgentConfig(
context: Contexts,
coreEnvironmentConfig?: CoreEnvironmentConfig<Chain>,
coreEnvironmentConfig?: CoreEnvironmentConfig,
) {
const coreConfig = coreEnvironmentConfig
? coreEnvironmentConfig
@ -103,10 +103,10 @@ export async function getAgentConfig<Chain extends ChainName>(
return agentConfig;
}
async function getKeyForRole<Chain extends ChainName>(
async function getKeyForRole(
environment: DeployEnvironment,
context: Contexts,
chain: Chain,
chain: ChainName,
role: KEY_ROLE_ENUM,
index?: number,
): Promise<CloudAgentKey> {
@ -115,14 +115,14 @@ async function getKeyForRole<Chain extends ChainName>(
return getCloudAgentKey(agentConfig, role, chain, index);
}
export async function getMultiProviderForRole<Chain extends ChainName>(
txConfigs: ChainMap<Chain, IChainConnection>,
export async function getMultiProviderForRole(
txConfigs: ChainMap<ChainMetadata>,
environment: DeployEnvironment,
context: Contexts,
role: KEY_ROLE_ENUM,
index?: number,
connectionType?: ConnectionType,
): Promise<MultiProvider<Chain>> {
): Promise<MultiProvider> {
const connections = await promiseObjAll(
objMap(txConfigs, async (chain, config) => {
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() {
@ -173,8 +173,8 @@ export function getKeyRoleAndChainArgs() {
.number('i');
}
export async function assertCorrectKubeContext<Chain extends ChainName>(
coreConfig: CoreEnvironmentConfig<Chain>,
export async function assertCorrectKubeContext(
coreConfig: CoreEnvironmentConfig,
) {
const currentKubeContext = await getCurrentKubernetesContext();
if (

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

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

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

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

@ -14,15 +14,13 @@ import { KEY_ROLE_ENUM } from '../roles';
import { AgentAwsKey } from './key';
import { AgentAwsUser } from './user';
export class ValidatorAgentAwsUser<
Chain extends ChainName,
> extends AgentAwsUser<Chain> {
export class ValidatorAgentAwsUser extends AgentAwsUser {
private adminS3Client: S3Client;
constructor(
environment: string,
context: Contexts,
public readonly chainName: Chain,
public readonly chainName: ChainName,
public readonly index: number,
region: string,
public readonly bucket: string,
@ -85,7 +83,7 @@ export class ValidatorAgentAwsUser<
await this.adminS3Client.send(cmd);
}
key(agentConfig: AgentConfig<Chain>): AgentAwsKey {
key(agentConfig: AgentConfig): AgentAwsKey {
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/';
async function helmValuesForChain<Chain extends ChainName>(
chainName: Chain,
agentConfig: AgentConfig<Chain>,
async function helmValuesForChain(
chainName: ChainName,
agentConfig: AgentConfig,
) {
const chainAgentConfig = new ChainAgentConfig(agentConfig, chainName);
const gelatoApiKeyRequired =
@ -94,10 +94,10 @@ async function helmValuesForChain<Chain extends ChainName>(
};
}
export async function getAgentEnvVars<Chain extends ChainName>(
outboxChainName: Chain,
export async function getAgentEnvVars(
outboxChainName: ChainName,
role: KEY_ROLE_ENUM,
agentConfig: AgentConfig<Chain>,
agentConfig: AgentConfig,
index?: number,
) {
const chainNames = agentConfig.contextChainNames;
@ -165,7 +165,7 @@ export async function getAgentEnvVars<Chain extends ChainName>(
} else {
// AWS keys
let user: AgentAwsUser<Chain>;
let user: AgentAwsUser;
if (role === KEY_ROLE_ENUM.Validator && agentConfig.validators) {
const checkpointSyncer =
@ -271,9 +271,7 @@ function configEnvVars(
return envVars;
}
export async function getSecretAwsCredentials<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
) {
export async function getSecretAwsCredentials(agentConfig: AgentConfig) {
return {
accessKeyId: await fetchGCPSecret(
`${agentConfig.runEnv}-aws-access-key-id`,
@ -312,10 +310,7 @@ export async function getSecretDeployerKey(
return key.privateKey;
}
async function getSecretRpcEndpoints<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
quorum = false,
) {
async function getSecretRpcEndpoints(agentConfig: AgentConfig, quorum = false) {
const environment = agentConfig.runEnv;
return Object.fromEntries(
agentConfig.contextChainNames.map((chainName) => [
@ -325,9 +320,9 @@ async function getSecretRpcEndpoints<Chain extends ChainName>(
);
}
export async function doesAgentReleaseExist<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
outboxChainName: Chain,
export async function doesAgentReleaseExist(
agentConfig: AgentConfig,
outboxChainName: ChainName,
) {
try {
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,
agentConfig: AgentConfig<Chain>,
outboxChainName: Chain,
agentConfig: AgentConfig,
outboxChainName: ChainName,
) {
if (action === HelmCommand.Remove) {
return execCmd(
@ -408,9 +403,9 @@ export async function runAgentHelmCommand<Chain extends ChainName>(
return;
}
function getHelmReleaseName<Chain extends ChainName>(
outboxChainName: Chain,
agentConfig: AgentConfig<Chain>,
function getHelmReleaseName(
outboxChainName: ChainName,
agentConfig: AgentConfig,
): string {
// For backward compatibility reasons, don't include the context
// in the name of the helm release if the context is the default "hyperlane"

@ -15,10 +15,10 @@ interface KeyAsAddress {
address: string;
}
export function getCloudAgentKey<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
export function getCloudAgentKey(
agentConfig: AgentConfig,
role: KEY_ROLE_ENUM,
chainName?: Chain,
chainName?: ChainName,
index?: number,
): CloudAgentKey {
if (
@ -40,7 +40,7 @@ export function getCloudAgentKey<Chain extends ChainName>(
}
export function getValidatorCloudAgentKeys(
agentConfig: AgentConfig<any>,
agentConfig: AgentConfig,
): Array<CloudAgentKey> {
// For each chainName, create validatorCount keys
return agentConfig.contextChainNames.flatMap((chainName) => {
@ -60,7 +60,7 @@ export function getValidatorCloudAgentKeys(
}
export function getRelayerCloudAgentKeys(
agentConfig: AgentConfig<any>,
agentConfig: AgentConfig,
): Array<CloudAgentKey> {
return agentConfig.contextChainNames.map((chainName) =>
getCloudAgentKey(agentConfig, KEY_ROLE_ENUM.Relayer, chainName),
@ -68,7 +68,7 @@ export function getRelayerCloudAgentKeys(
}
export function getAllCloudAgentKeys(
agentConfig: AgentConfig<any>,
agentConfig: AgentConfig,
): Array<CloudAgentKey> {
return agentConfig.rolesWithKeys.flatMap((role) => {
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);
await Promise.all(keys.map((key) => key.delete()));
await execCmd(
@ -92,9 +92,7 @@ export async function deleteAgentKeys(agentConfig: AgentConfig<any>) {
);
}
export async function createAgentKeysIfNotExists(
agentConfig: AgentConfig<any>,
) {
export async function createAgentKeysIfNotExists(agentConfig: AgentConfig) {
const keys = getAllCloudAgentKeys(agentConfig);
await Promise.all(
@ -110,10 +108,10 @@ export async function createAgentKeysIfNotExists(
);
}
export async function rotateKey<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
export async function rotateKey(
agentConfig: AgentConfig,
role: KEY_ROLE_ENUM,
chainName: Chain,
chainName: ChainName,
) {
const key = getCloudAgentKey(agentConfig, role, chainName);
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
export async function fetchKeysForChain<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
chainName: Chain,
export async function fetchKeysForChain(
agentConfig: AgentConfig,
chainName: ChainName,
): Promise<Record<string, CloudAgentKey>> {
// 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

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

@ -1,7 +1,6 @@
import { FallbackProviderConfig } from '@ethersproject/providers';
import { ethers } from 'ethers';
import { StaticCeloJsonRpcProvider } from '@hyperlane-xyz/celo-ethers-provider';
import { ChainName, RetryJsonRpcProvider } from '@hyperlane-xyz/sdk';
import { getSecretRpcEndpoint } from '../agents';
@ -9,15 +8,7 @@ import { getSecretRpcEndpoint } from '../agents';
import { ConnectionType } from './agent';
import { DeployEnvironment } from './environment';
const CELO_CHAIN_NAMES = new Set(['alfajores', 'baklava', 'celo']);
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 providerBuilder = (url: string, retry = true) => {
const baseProvider = new ethers.providers.JsonRpcProvider(url);
return retry
? new RetryJsonRpcProvider(baseProvider, {
@ -36,20 +27,18 @@ export async function fetchProvider(
const rpcData = await getSecretRpcEndpoint(environment, chainName, !single);
switch (connectionType) {
case ConnectionType.Http: {
return providerBuilder(rpcData, chainName);
return providerBuilder(rpcData);
}
case ConnectionType.HttpQuorum: {
return new ethers.providers.FallbackProvider(
(rpcData as string[]).map((url) =>
providerBuilder(url, chainName, false),
), // disable retry for quorum
(rpcData as string[]).map((url) => providerBuilder(url, false)), // disable retry for quorum
);
}
case ConnectionType.HttpFallback: {
return new ethers.providers.FallbackProvider(
(rpcData as string[]).map((url, index) => {
const fallbackProviderConfig: FallbackProviderConfig = {
provider: providerBuilder(url, chainName),
provider: providerBuilder(url),
// Priority is used by the FallbackProvider to determine
// how to order providers using ascending ordering.
// When not specified, all providers have the same priority

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

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

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

@ -4,7 +4,6 @@ import { InterchainGasPaymaster__factory } from '@hyperlane-xyz/core';
import {
ChainMap,
ChainName,
ChainNameToDomainId,
CoreContracts,
CoreViolationType,
EnrolledValidatorsViolation,
@ -39,12 +38,12 @@ type AnnotatedCallData = types.CallData & {
description: string;
};
export class HyperlaneCoreGovernor<Chain extends ChainName> {
readonly checker: HyperlaneCoreChecker<Chain>;
private calls: ChainMap<Chain, AnnotatedCallData[]>;
private canPropose: ChainMap<Chain, Map<string, boolean>>;
export class HyperlaneCoreGovernor {
readonly checker: HyperlaneCoreChecker;
private calls: ChainMap<AnnotatedCallData[]>;
private canPropose: ChainMap<Map<string, boolean>>;
constructor(checker: HyperlaneCoreChecker<Chain>) {
constructor(checker: HyperlaneCoreChecker) {
this.checker = checker;
this.calls = objMap(this.checker.app.contractsMap, () => []);
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,
// 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);
}
}
protected async sendCalls(chain: Chain) {
protected async sendCalls(chain: ChainName) {
const calls = this.calls[chain];
console.log(`\nFound ${calls.length} transactions for ${chain}`);
const filterCalls = (submissionType: SubmissionType) =>
@ -109,21 +108,19 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
}
};
const connection = this.checker.multiProvider.getChainConnection(chain);
await sendCallsForType(
SubmissionType.SIGNER,
new SignerMultiSend(connection),
new SignerMultiSend(this.checker.multiProvider, chain),
);
const owner = this.checker.configMap[chain!].owner!;
await sendCallsForType(
SubmissionType.SAFE,
new SafeMultiSend(connection, chain, owner),
new SafeMultiSend(this.checker.multiProvider, chain, owner),
);
await sendCallsForType(SubmissionType.MANUAL, new ManualMultiSend(chain));
}
protected pushCall(chain: Chain, call: AnnotatedCallData) {
protected pushCall(chain: ChainName, call: AnnotatedCallData) {
this.calls[chain].push(call);
}
@ -150,7 +147,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
handleProxyViolation(violation: ProxyViolation) {
const contracts: CoreContracts =
this.checker.app.contractsMap[violation.chain as Chain];
this.checker.app.contractsMap[violation.chain];
let initData = '0x';
switch (violation.data.name) {
case 'InterchainGasPaymaster':
@ -162,7 +159,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
default:
throw new Error(`Unsupported proxy violation ${violation.data.name}`);
}
this.pushCall(violation.chain as Chain, {
this.pushCall(violation.chain, {
to: contracts.proxyAdmin.address,
data: contracts.proxyAdmin.interface.encodeFunctionData(
'upgradeAndCall',
@ -177,7 +174,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
}
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]) {
const submissionType = await this.inferCallSubmissionType(chain, call);
call.submissionType = submissionType;
@ -186,13 +183,13 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
}
protected async inferCallSubmissionType(
chain: Chain,
chain: ChainName,
call: AnnotatedCallData,
): 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.
try {
await connection.estimateGas(call);
await multiProvider.estimateGas(chain, call);
return SubmissionType.SIGNER;
} 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.
// This should implicitly check whether or not the owner is a gnosis
// safe.
const signer = connection.signer;
const signer = multiProvider.getSigner(chain);
if (!signer) throw new Error(`no signer found`);
const signerAddress = await signer.getAddress();
if (!this.canPropose[chain].has(safeAddress)) {
@ -211,7 +208,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
await canProposeSafeTransactions(
signerAddress,
chain,
connection,
multiProvider,
safeAddress,
),
);
@ -220,7 +217,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
// 2b. Check if calling from the owner will succeed.
if (this.canPropose[chain].get(safeAddress)) {
try {
await connection.provider.estimateGas({
await multiProvider.getProvider(chain).estimateGas({
...call,
from: safeAddress,
});
@ -242,21 +239,21 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
// add expected - actual elements
utils
.difference(reconcile.expected, reconcile.actual)
.forEach((elem) =>
this.pushCall(reconcile.chain as Chain, reconcile.add(elem)),
);
.forEach((elem) => this.pushCall(reconcile.chain, reconcile.add(elem)));
// remote actual - expected elements
utils
.difference(reconcile.actual, reconcile.expected)
.forEach((elem) =>
this.pushCall(reconcile.chain as Chain, reconcile.remove(elem)),
this.pushCall(reconcile.chain, reconcile.remove(elem)),
);
}
handleMultisigIsmViolation(violation: MultisigIsmViolation) {
const multisigIsm = violation.contract;
const remoteDomainId = ChainNameToDomainId[violation.remote];
const remoteDomainId = this.checker.multiProvider.getDomainId(
violation.remote,
);
switch (violation.subType) {
case MultisigIsmViolationType.EnrolledValidators: {
const baseDescription = `as ${violation.remote} validator on ${violation.chain}`;
@ -282,7 +279,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
break;
}
case MultisigIsmViolationType.Threshold: {
this.pushCall(violation.chain as Chain, {
this.pushCall(violation.chain, {
to: multisigIsm.address,
data: multisigIsm.interface.encodeFunctionData('setThreshold', [
remoteDomainId,
@ -300,7 +297,7 @@ export class HyperlaneCoreGovernor<Chain extends ChainName> {
}
handleOwnerViolation(violation: OwnerViolation) {
this.pushCall(violation.chain as Chain, {
this.pushCall(violation.chain, {
to: violation.contract.address,
data: violation.contract.interface.encodeFunctionData(
'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 { getSafe, getSafeService } from '../utils/safe';
@ -8,16 +8,19 @@ export abstract class MultiSend {
}
export class SignerMultiSend extends MultiSend {
readonly connection: ChainConnection;
constructor(connection: ChainConnection) {
constructor(
public readonly multiProvider: MultiProvider,
public readonly chain: ChainName,
) {
super();
this.connection = connection;
}
async sendTransactions(calls: types.CallData[]) {
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}`);
}
}
@ -38,23 +41,20 @@ export class ManualMultiSend extends MultiSend {
}
export class SafeMultiSend extends MultiSend {
readonly connection: ChainConnection;
readonly chain: ChainName;
readonly safeAddress: string;
constructor(
connection: ChainConnection,
chain: ChainName,
safeAddress: string,
public readonly multiProvider: MultiProvider,
public readonly chain: ChainName,
public readonly safeAddress: string,
) {
super();
this.connection = connection;
this.chain = chain;
this.safeAddress = safeAddress;
}
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) => {
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 senderSignature = await safeSdk.signTransactionHash(safeTxHash);
const safeService = getSafeService(this.chain, this.connection);
if (!this.connection.signer) throw new Error('missing signer');
const safeService = getSafeService(this.chain, this.multiProvider);
const senderAddress = await this.multiProvider.getSignerAddress(this.chain);
await safeService.proposeTransaction({
safeAddress: this.safeAddress,
safeTransactionData: safeTransaction.data,
safeTxHash,
senderAddress: await this.connection.signer.getAddress()!,
senderAddress,
senderSignature: senderSignature.data,
});
}

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

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

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

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

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

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

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

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

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

@ -5,7 +5,7 @@ import { ethers } from 'ethers';
import fs from 'fs';
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 { ALL_KEY_ROLES, KEY_ROLE_ENUM } from '../agents/roles';
@ -187,7 +187,7 @@ export function assertRole(roleStr: string) {
export function assertChain(chainStr: string) {
const chain = chainStr as ChainName;
if (!AllChains.includes(chain)) {
if (!AllChains.includes(chain as CoreChainName)) {
throw Error(`Invalid chain ${chain}`);
}
return chain;

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

@ -3970,11 +3970,11 @@ __metadata:
languageName: node
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
resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld"
dependencies:
"@hyperlane-xyz/sdk": 1.1.4
"@hyperlane-xyz/sdk": 1.2.0
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3
"@openzeppelin/contracts-upgradeable": ^4.8.0
@ -4051,10 +4051,9 @@ __metadata:
"@gnosis.pm/safe-core-sdk": ^2.3.2
"@gnosis.pm/safe-ethers-lib": ^1.4.0
"@gnosis.pm/safe-service-client": ^1.2.0
"@hyperlane-xyz/celo-ethers-provider": ^0.1.1
"@hyperlane-xyz/helloworld": 1.1.4
"@hyperlane-xyz/sdk": 1.1.4
"@hyperlane-xyz/utils": 1.1.4
"@hyperlane-xyz/helloworld": 1.2.0
"@hyperlane-xyz/sdk": 1.2.0
"@hyperlane-xyz/utils": 1.2.0
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-etherscan": ^3.0.3
"@nomiclabs/hardhat-waffle": ^2.0.3
@ -4097,23 +4096,7 @@ __metadata:
languageName: unknown
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/sdk@workspace:typescript/sdk":
"@hyperlane-xyz/sdk@1.2.0, @hyperlane-xyz/sdk@workspace:typescript/sdk":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk"
dependencies:
@ -4142,6 +4125,22 @@ __metadata:
languageName: unknown
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":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/utils@workspace:typescript/utils"

Loading…
Cancel
Save