fix: use secret RPC urls in infra, apply environment-specific registry overrides (#3875)

### Description

A while back, it seems secret RPC URLs stopped being used by monorepo
services (see
https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/3179/files#diff-ba3b7bea2b5c046acd88d25ed382df875b49d77e061f2ef8347ffcc741c0353eR34).
This adds them back.

Some things to note on the approach:
- Sadly, due to the way some of the infra config generation works, we're
forced to use synchronous interfaces for getting chain metadata in a
bunch of places. This is why `getRegistry` returns a
`FileSystemRegistry`, which is a `SynchronousRegistry`.
- Applying secrets / overrides requires us to do things async for two
reasons -- one is just that fetching from GCP secrets is an async
operation, the other is that a `MergedRegistry` is not a
`SynchronousRegistry`. The approach I've taken is that there are two
ways of getting a registry - using `getRegistry` will give the
synchronous version that can continue to be used by our sync config
generation, but it won't have any environment-specific overrides (tx
overrides or secrets). To get an async registry with
environment-specific overrides, the `getRegistry` function on the
EnvironmentConfig is used.
- Overrides are now more succinct as the merging happens later in the
pipeline

### Drive-by changes

- Started moving away from using the gcloud CLI under the hood for GCP
operations and toward using the GCP secret SDK
- Updated the mainnet3 key funder to fix an incident, but will follow up
with a fresh deploy once this is mergd

### Related issues

- These are the code changes for
https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3774, but
I'll follow up with fresh deploys for the monorepo services

### Backward compatibility

<!--
Are these changes backward compatible? Are there any infrastructure
implications, e.g. changes that would prohibit deploying older commits
using this infra tooling?

Yes/No
-->

### Testing

<!--
What kind of testing have these changes undergone?

None/Manual/Unit Tests
-->

---------

Co-authored-by: Connor McEwen <connor.mcewen@gmail.com>
Co-authored-by: Yorke Rhodes <yorke@hyperlane.xyz>
Co-authored-by: J M Rossy <jm.rossy@gmail.com>
noah/dr-fix
Trevor Porter 6 months ago committed by GitHub
parent 8a6654477e
commit db9f733e4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 49
      rust/config/mainnet_config.json
  2. 28
      typescript/infra/config/environments/mainnet3/chains.ts
  3. 2
      typescript/infra/config/environments/mainnet3/funding.ts
  4. 48
      typescript/infra/config/environments/mainnet3/index.ts
  5. 9
      typescript/infra/config/environments/test/index.ts
  6. 15
      typescript/infra/config/environments/testnet4/chains.ts
  7. 33
      typescript/infra/config/environments/testnet4/index.ts
  8. 39
      typescript/infra/config/registry.ts
  9. 1
      typescript/infra/package.json
  10. 58
      typescript/infra/scripts/agent-utils.ts
  11. 8
      typescript/infra/scripts/agents/update-agent-config.ts
  12. 10
      typescript/infra/scripts/check-rpc-urls.ts
  13. 4
      typescript/infra/scripts/funding/fund-keys-from-deployer.ts
  14. 12
      typescript/infra/scripts/helloworld/kathy.ts
  15. 12
      typescript/infra/scripts/print-chain-metadatas.ts
  16. 46
      typescript/infra/scripts/print-gas-prices.ts
  17. 12
      typescript/infra/scripts/print-token-prices.ts
  18. 8
      typescript/infra/src/agents/index.ts
  19. 81
      typescript/infra/src/config/chain.ts
  20. 8
      typescript/infra/src/config/environment.ts
  21. 30
      typescript/infra/src/utils/gcloud.ts
  22. 4
      typescript/infra/src/utils/utils.ts
  23. 10
      typescript/sdk/src/metadata/agentConfig.ts
  24. 315
      yarn.lock

@ -634,13 +634,19 @@
},
"injective": {
"bech32Prefix": "inj",
"blockExplorers": [
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 1,
"reorgPeriod": 10
},
"canonicalAsset": "inj",
"chainId": "injective-1",
"contractAddressBytes": 20,
"domainId": "6909546",
"displayName": "Injective",
"domainId": 6909546,
"gasCurrencyCoinGeckoId": "injective-protocol",
"gasPrice": {
"amount": "700000000",
"denom": "inj"
@ -658,12 +664,24 @@
"mailbox": "0x0f7fb53961d70687e352aa55cb329ca76edc0c19",
"merkleTreeHook": "0x568ad3638447f07def384969f4ea39fae3802962",
"name": "injective",
"nativeToken": {
"decimals": 18,
"denom": "inj",
"name": "Injective",
"symbol": "INJ"
},
"protocol": "cosmos",
"restUrls": [
{
"http": "https://sentry.lcd.injective.network:443"
}
],
"rpcUrls": [
{
"http": "https://injective-rpc.polkachu.com"
"http": "https://sentry.tm.injective.network:443"
}
],
"slip44": 118,
"validatorAnnounce": "0x1fb225b2fcfbe75e614a1d627de97ff372242eed"
},
"mantapacific": {
@ -837,13 +855,25 @@
},
"neutron": {
"bech32Prefix": "neutron",
"blockExplorers": [
{
"apiUrl": "https://www.mintscan.io/neutron",
"family": "other",
"name": "Mintscan",
"url": "https://www.mintscan.io/neutron"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 3,
"reorgPeriod": 1
},
"canonicalAsset": "untrn",
"chainId": "neutron-1",
"contractAddressBytes": 32,
"domainId": "1853125230",
"displayName": "Neutron",
"domainId": 1853125230,
"gasCurrencyCoinGeckoId": "neutron-3",
"gasPrice": {
"amount": "0.0053",
"denom": "untrn"
@ -858,10 +888,22 @@
"from": 4000000
},
"interchainGasPaymaster": "0x504ee9ac43ec5814e00c7d21869a90ec52becb489636bdf893b7df9d606b5d67",
"isTestnet": false,
"mailbox": "0x848426d50eb2104d5c6381ec63757930b1c14659c40db8b8081e516e7c5238fc",
"merkleTreeHook": "0xcd30a0001cc1f436c41ef764a712ebabc5a144140e3fd03eafe64a9a24e4e27c",
"name": "neutron",
"nativeToken": {
"decimals": 6,
"denom": "untrn",
"name": "Neutron",
"symbol": "NTRN"
},
"protocol": "cosmos",
"restUrls": [
{
"http": "https://rest-lb.neutron.org"
}
],
"rpcUrls": [
{
"http": "https://rpc-kralum.neutron-1.neutron.org"
@ -872,6 +914,7 @@
"prefix": "neutron",
"type": "cosmosKey"
},
"slip44": 118,
"validatorAnnounce": "0xf3aa0d652226e21ae35cd9035c492ae41725edc9036edf0d6a48701b153b90a0"
},
"optimism": {

@ -1,30 +1,23 @@
import { ChainMap, ChainMetadata } from '@hyperlane-xyz/sdk';
import { objKeys } from '@hyperlane-xyz/utils';
import { getChainMetadatas } from '../../../src/config/chain.js';
import { getChain } from '../../registry.js';
import { isEthereumProtocolChain } from '../../../src/utils/utils.js';
import { supportedChainNames } from './supportedChainNames.js';
export const environment = 'mainnet3';
const {
ethereumMetadatas: defaultEthereumMainnetConfigs,
nonEthereumMetadatas: nonEthereumMainnetConfigs,
} = getChainMetadatas(supportedChainNames);
export const ethereumChainNames = supportedChainNames.filter(
isEthereumProtocolChain,
);
export const ethereumMainnetConfigs: ChainMap<ChainMetadata> = {
...defaultEthereumMainnetConfigs,
export const chainMetadataOverrides: ChainMap<Partial<ChainMetadata>> = {
bsc: {
...getChain('bsc'),
transactionOverrides: {
gasPrice: 3 * 10 ** 9, // 3 gwei
},
},
polygon: {
...getChain('polygon'),
blocks: {
...getChain('polygon').blocks,
confirmations: 3,
},
transactionOverrides: {
@ -35,9 +28,7 @@ export const ethereumMainnetConfigs: ChainMap<ChainMetadata> = {
},
},
ethereum: {
...getChain('ethereum'),
blocks: {
...getChain('ethereum').blocks,
confirmations: 3,
},
transactionOverrides: {
@ -46,7 +37,6 @@ export const ethereumMainnetConfigs: ChainMap<ChainMetadata> = {
},
},
scroll: {
...getChain('scroll'),
transactionOverrides: {
// Scroll doesn't use EIP 1559 and the gas price that's returned is sometimes
// too low for the transaction to be included in a reasonable amount of time -
@ -55,17 +45,9 @@ export const ethereumMainnetConfigs: ChainMap<ChainMetadata> = {
},
},
moonbeam: {
...getChain('moonbeam'),
transactionOverrides: {
maxFeePerGas: 350 * 10 ** 9, // 350 gwei
maxPriorityFeePerGas: 50 * 10 ** 9, // 50 gwei
},
},
};
export const mainnetConfigs: ChainMap<ChainMetadata> = {
...ethereumMainnetConfigs,
...nonEthereumMainnetConfigs,
};
export const ethereumChainNames = objKeys(ethereumMainnetConfigs);

@ -9,7 +9,7 @@ import { environment } from './chains.js';
export const keyFunderConfig: KeyFunderConfig = {
docker: {
repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo',
tag: 'b22a0f4-20240523-140812',
tag: '7720875-20240531-072251',
},
// We're currently using the same deployer/key funder key as mainnet2.
// To minimize nonce clobbering we offset the key funder cron

@ -1,16 +1,21 @@
import { ChainMetadata, RpcConsensusType } from '@hyperlane-xyz/sdk';
import { ProtocolType, objFilter } from '@hyperlane-xyz/utils';
import { IRegistry } from '@hyperlane-xyz/registry';
import { RpcConsensusType } from '@hyperlane-xyz/sdk';
import {
getKeysForRole,
getMultiProtocolProvider,
getMultiProviderForRole,
} from '../../../scripts/agent-utils.js';
import { getRegistryForEnvironment } from '../../../src/config/chain.js';
import { EnvironmentConfig } from '../../../src/config/environment.js';
import { Role } from '../../../src/roles.js';
import { Contexts } from '../../contexts.js';
import { agents } from './agent.js';
import { environment as environmentName, mainnetConfigs } from './chains.js';
import {
chainMetadataOverrides,
environment as environmentName,
} from './chains.js';
import { core } from './core.js';
import { keyFunderConfig } from './funding.js';
import { helloWorld } from './helloworld.js';
@ -18,34 +23,39 @@ import { igp } from './igp.js';
import { infrastructure } from './infrastructure.js';
import { bridgeAdapterConfigs, relayerConfig } from './liquidityLayer.js';
import { owners } from './owners.js';
import { supportedChainNames } from './supportedChainNames.js';
const getRegistry = async (useSecrets = true): Promise<IRegistry> =>
getRegistryForEnvironment(
environmentName,
supportedChainNames,
chainMetadataOverrides,
useSecrets,
);
export const environment: EnvironmentConfig = {
environment: environmentName,
chainMetadataConfigs: mainnetConfigs,
getMultiProvider: (
supportedChainNames,
getRegistry,
getMultiProtocolProvider: async () =>
getMultiProtocolProvider(await getRegistry()),
getMultiProvider: async (
context: Contexts = Contexts.Hyperlane,
role: Role = Role.Deployer,
connectionType?: RpcConsensusType,
) => {
const config = objFilter(
mainnetConfigs,
(_, chainMetadata): chainMetadata is ChainMetadata =>
chainMetadata.protocol === ProtocolType.Ethereum,
);
return getMultiProviderForRole(
config,
_connectionType?: RpcConsensusType,
useSecrets?: boolean,
) =>
getMultiProviderForRole(
environmentName,
await getRegistry(useSecrets),
context,
role,
undefined,
connectionType,
);
},
),
getKeys: (
context: Contexts = Contexts.Hyperlane,
role: Role = Role.Deployer,
) => getKeysForRole(mainnetConfigs, environmentName, context, role),
) => getKeysForRole(environmentName, supportedChainNames, context, role),
agents,
core,
igp,

@ -5,6 +5,7 @@ import { MultiProvider, testChainMetadata } from '@hyperlane-xyz/sdk';
import { EnvironmentConfig } from '../../../src/config/environment.js';
import { agents } from './agent.js';
import { testChainNames } from './chains.js';
import { core } from './core.js';
import { igp } from './igp.js';
import { infra } from './infra.js';
@ -12,7 +13,13 @@ import { owners } from './owners.js';
export const environment: EnvironmentConfig = {
environment: 'test',
chainMetadataConfigs: testChainMetadata,
supportedChainNames: testChainNames,
getRegistry: () => {
throw new Error('Not implemented');
},
getMultiProtocolProvider: () => {
throw new Error('Not implemented');
},
agents,
core,
igp,

@ -1,24 +1,19 @@
import { ChainMap, ChainMetadata } from '@hyperlane-xyz/sdk';
import { objKeys } from '@hyperlane-xyz/utils';
import { getChainMetadatas } from '../../../src/config/chain.js';
import { getChain } from '../../registry.js';
import { isEthereumProtocolChain } from '../../../src/utils/utils.js';
import { supportedChainNames } from './supportedChainNames.js';
export const environment = 'testnet4';
const { ethereumMetadatas: defaultEthereumMainnetConfigs } =
getChainMetadatas(supportedChainNames);
export const ethereumChainNames = supportedChainNames.filter(
isEthereumProtocolChain,
);
export const testnetConfigs: ChainMap<ChainMetadata> = {
...defaultEthereumMainnetConfigs,
export const chainMetadataOverrides: ChainMap<Partial<ChainMetadata>> = {
bsctestnet: {
...getChain('bsctestnet'),
transactionOverrides: {
gasPrice: 8 * 10 ** 9, // 8 gwei
},
},
};
export const ethereumChainNames = objKeys(defaultEthereumMainnetConfigs);

@ -1,15 +1,22 @@
import { IRegistry } from '@hyperlane-xyz/registry';
import { RpcConsensusType } from '@hyperlane-xyz/sdk';
import { objMerge } from '@hyperlane-xyz/utils';
import {
getKeysForRole,
getMultiProtocolProvider,
getMultiProviderForRole,
} from '../../../scripts/agent-utils.js';
import { getRegistryForEnvironment } from '../../../src/config/chain.js';
import { EnvironmentConfig } from '../../../src/config/environment.js';
import { Role } from '../../../src/roles.js';
import { Contexts } from '../../contexts.js';
import { agents } from './agent.js';
import { environment as environmentName, testnetConfigs } from './chains.js';
import {
chainMetadataOverrides,
environment as environmentName,
} from './chains.js';
import { core } from './core.js';
import { keyFunderConfig } from './funding.js';
import { helloWorld } from './helloworld.js';
@ -18,27 +25,39 @@ import { infrastructure } from './infrastructure.js';
import { bridgeAdapterConfigs } from './liquidityLayer.js';
import { liquidityLayerRelayerConfig } from './middleware.js';
import { owners } from './owners.js';
import { supportedChainNames } from './supportedChainNames.js';
const getRegistry = async (useSecrets = true): Promise<IRegistry> =>
getRegistryForEnvironment(
environmentName,
supportedChainNames,
chainMetadataOverrides,
useSecrets,
);
export const environment: EnvironmentConfig = {
environment: environmentName,
chainMetadataConfigs: testnetConfigs,
getMultiProvider: (
supportedChainNames,
getRegistry,
getMultiProtocolProvider: async () =>
getMultiProtocolProvider(await getRegistry()),
getMultiProvider: async (
context: Contexts = Contexts.Hyperlane,
role: Role = Role.Deployer,
connectionType?: RpcConsensusType,
_connectionType?: RpcConsensusType,
useSecrets?: boolean,
) =>
getMultiProviderForRole(
testnetConfigs,
environmentName,
await getRegistry(useSecrets),
context,
role,
undefined,
connectionType,
),
getKeys: (
context: Contexts = Contexts.Hyperlane,
role: Role = Role.Deployer,
) => getKeysForRole(testnetConfigs, environmentName, context, role),
) => getKeysForRole(environmentName, supportedChainNames, context, role),
agents,
core,
igp,

@ -1,7 +1,11 @@
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { ChainAddresses } from '@hyperlane-xyz/registry';
import {
ChainAddresses,
MergedRegistry,
PartialRegistry,
} from '@hyperlane-xyz/registry';
import { FileSystemRegistry } from '@hyperlane-xyz/registry/fs';
import {
ChainMap,
@ -35,10 +39,18 @@ export function setRegistry(reg: FileSystemRegistry) {
registry = reg;
}
/**
* Gets a FileSystemRegistry whose contents are found at the environment
* variable `REGISTRY_URI`, or `DEFAULT_REGISTRY_URI` if no env var is specified.
* This registry will not have any environment-specific overrides applied,
* and is useful for synchronous registry operations that do not require
* any overrides.
* @returns A FileSystemRegistry.
*/
export function getRegistry(): FileSystemRegistry {
if (!registry) {
const registryUri = process.env.REGISTRY_URI || DEFAULT_REGISTRY_URI;
rootLogger.info('Using registry URI:', registryUri);
rootLogger.info({ registryUri }, 'Using registry URI');
registry = new FileSystemRegistry({
uri: registryUri,
logger: rootLogger.child({ module: 'infra-registry' }),
@ -111,3 +123,26 @@ export function getMainnetAddresses(): ChainMap<ChainAddresses> {
export function getTestnetAddresses(): ChainMap<ChainAddresses> {
return getEnvAddresses('testnet4');
}
/**
* Gets a registry, applying the provided overrides. The base registry
* that the overrides are applied to is the registry returned by `getRegistry`.
* @param chainMetadataOverrides Chain metadata overrides.
* @param chainAddressesOverrides Chain address overrides.
* @returns A MergedRegistry merging the registry from `getRegistry` and the overrides.
*/
export function getRegistryWithOverrides(
chainMetadataOverrides: ChainMap<Partial<ChainMetadata>> = {},
chainAddressesOverrides: ChainMap<Partial<ChainAddresses>> = {},
): MergedRegistry {
const baseRegistry = getRegistry();
const overrideRegistry = new PartialRegistry({
chainMetadata: chainMetadataOverrides,
chainAddresses: chainAddressesOverrides,
});
return new MergedRegistry({
registries: [baseRegistry, overrideRegistry],
});
}

@ -12,6 +12,7 @@
"@ethersproject/experimental": "^5.7.0",
"@ethersproject/hardware-wallets": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@google-cloud/secret-manager": "^5.5.0",
"@hyperlane-xyz/helloworld": "3.13.0",
"@hyperlane-xyz/registry": "1.3.0",
"@hyperlane-xyz/sdk": "3.13.0",

@ -1,12 +1,13 @@
import path, { join } from 'path';
import yargs, { Argv } from 'yargs';
import { ChainAddresses } from '@hyperlane-xyz/registry';
import { ChainAddresses, IRegistry } from '@hyperlane-xyz/registry';
import {
ChainMap,
ChainMetadata,
ChainName,
CoreConfig,
MultiProtocolProvider,
MultiProvider,
RpcConsensusType,
collectValidators,
@ -16,6 +17,7 @@ import {
ProtocolType,
objFilter,
objMap,
objMerge,
promiseObjAll,
rootLogger,
symmetricDifference,
@ -35,7 +37,10 @@ import { getCurrentKubernetesContext } from '../src/agents/index.js';
import { getCloudAgentKey } from '../src/agents/key-utils.js';
import { CloudAgentKey } from '../src/agents/keys.js';
import { RootAgentConfig } from '../src/config/agent/agent.js';
import { fetchProvider } from '../src/config/chain.js';
import {
fetchProvider,
getSecretMetadataOverrides,
} from '../src/config/chain.js';
import {
AgentEnvironment,
DeployEnvironment,
@ -47,6 +52,7 @@ import {
assertContext,
assertRole,
getInfraPath,
inCIMode,
readJSONAtPath,
writeMergedJSONAtPath,
} from '../src/utils/utils.js';
@ -283,8 +289,8 @@ export function ensureValidatorConfigConsistency(agentConfig: RootAgentConfig) {
export function getKeyForRole(
environment: DeployEnvironment,
context: Contexts,
chain: ChainName,
role: Role,
chain?: ChainName,
index?: number,
): CloudAgentKey {
debugLog(`Getting key for ${role} role`);
@ -292,33 +298,32 @@ export function getKeyForRole(
return getCloudAgentKey(agentConfig, role, chain, index);
}
export async function getMultiProtocolProvider(
registry: IRegistry,
): Promise<MultiProtocolProvider> {
const chainMetadata = await registry.getMetadata();
return new MultiProtocolProvider(chainMetadata);
}
export async function getMultiProviderForRole(
txConfigs: ChainMap<ChainMetadata>,
environment: DeployEnvironment,
registry: IRegistry,
context: Contexts,
role: Role,
index?: number,
// TODO: rename to consensusType?
connectionType?: RpcConsensusType,
): Promise<MultiProvider> {
const chainMetadata = await registry.getMetadata();
debugLog(`Getting multiprovider for ${role} role`);
const multiProvider = new MultiProvider(txConfigs);
if (process.env.CI === 'true') {
debugLog('Returning multiprovider with default RPCs in CI');
// Return the multiProvider with default RPCs
const multiProvider = new MultiProvider(chainMetadata);
if (inCIMode()) {
debugLog('Running in CI, returning multiprovider without secret keys');
return multiProvider;
}
await promiseObjAll(
objMap(txConfigs, async (chain, _) => {
objMap(chainMetadata, async (chain, _) => {
if (multiProvider.getProtocol(chain) === ProtocolType.Ethereum) {
const provider = await fetchProvider(
environment,
chain,
connectionType,
);
const key = getKeyForRole(environment, context, chain, role, index);
const signer = await key.getSigner(provider);
multiProvider.setProvider(chain, provider);
const key = getKeyForRole(environment, context, role, chain, index);
const signer = await key.getSigner();
multiProvider.setSigner(chain, signer);
}
}),
@ -330,23 +335,22 @@ export async function getMultiProviderForRole(
// Note: this will only work for keystores that allow key's to be extracted.
// I.e. GCP will work but AWS HSMs will not.
export async function getKeysForRole(
txConfigs: ChainMap<ChainMetadata>,
environment: DeployEnvironment,
supportedChainNames: ChainName[],
context: Contexts,
role: Role,
index?: number,
): Promise<ChainMap<CloudAgentKey>> {
if (process.env.CI === 'true') {
if (inCIMode()) {
debugLog('No keys to return in CI');
return {};
}
const keys = await promiseObjAll(
objMap(txConfigs, async (chain, _) =>
getKeyForRole(environment, context, chain, role, index),
),
);
return keys;
const keyEntries = supportedChainNames.map((chain) => [
chain,
getKeyForRole(environment, context, role, chain, index),
]);
return Object.fromEntries(keyEntries);
}
export function getEnvironmentDirectory(environment: DeployEnvironment) {

@ -6,7 +6,13 @@ async function main() {
const { environment } = await getArgs().argv;
const envConfig = getEnvironmentConfig(environment);
let multiProvider = await envConfig.getMultiProvider();
let multiProvider = await envConfig.getMultiProvider(
undefined,
undefined,
undefined,
// Don't use secrets
false,
);
await writeAgentConfig(multiProvider, environment);
}

@ -2,24 +2,22 @@ import { ethers } from 'ethers';
import { rootLogger } from '@hyperlane-xyz/utils';
import { getSecretRpcEndpoint } from '../src/agents/index.js';
import { getSecretRpcEndpoints } from '../src/agents/index.js';
import { getArgs } from './agent-utils.js';
import { getEnvironmentConfig } from './core-utils.js';
// TODO remove this script as part of migration to CLI
// It's redundant with metadata-check.ts in the SDK
async function main() {
const { environment } = await getArgs().argv;
const config = await getEnvironmentConfig(environment);
const config = getEnvironmentConfig(environment);
const multiProvider = await config.getMultiProvider();
const chains = multiProvider.getKnownChainNames();
const providers: [string, ethers.providers.JsonRpcProvider][] = [];
for (const chain of chains) {
rootLogger.debug(`Building providers for ${chain}`);
const rpcData = [
...(await getSecretRpcEndpoint(environment, chain, false)),
...(await getSecretRpcEndpoint(environment, chain, true)),
...(await getSecretRpcEndpoints(environment, chain, false)),
...(await getSecretRpcEndpoints(environment, chain, true)),
];
for (const url of rpcData)
providers.push([chain, new ethers.providers.StaticJsonRpcProvider(url)]);

@ -381,7 +381,7 @@ class ContextFunder {
[Role.Kathy]: '',
};
const roleKeysPerChain: ChainMap<Record<FundableRole, BaseAgentKey[]>> = {};
const chains = getEnvironmentConfig(environment).chainMetadataConfigs;
const { supportedChainNames } = getEnvironmentConfig(environment);
for (const role of rolesToFund) {
assertFundableRole(role); // only the relayer and kathy are fundable keys
const roleAddress = fetchLocalKeyAddresses(role)[environment][context];
@ -392,7 +392,7 @@ class ContextFunder {
}
fundableRoleKeys[role] = roleAddress;
for (const chain of Object.keys(chains)) {
for (const chain of supportedChainNames) {
if (!roleKeysPerChain[chain as ChainName]) {
roleKeysPerChain[chain as ChainName] = {
[Role.Relayer]: [],

@ -20,6 +20,7 @@ import {
ProtocolType,
ensure0x,
objMap,
pick,
retryAsync,
rootLogger,
sleep,
@ -28,7 +29,6 @@ import {
} from '@hyperlane-xyz/utils';
import { Contexts } from '../../config/contexts.js';
import { testnetConfigs } from '../../config/environments/testnet4/chains.js';
import {
hyperlaneHelloworld,
releaseCandidateHelloworld,
@ -166,7 +166,6 @@ async function main(): Promise<boolean> {
logger.debug('Starting up', { environment });
const coreConfig = getEnvironmentConfig(environment);
// const coreConfig = getCoreConfigStub(environment);
const { app, core, igp, multiProvider, keys } =
await getHelloWorldMultiProtocolApp(
@ -550,7 +549,14 @@ async function updateWalletBalanceMetricFor(
}
// Get a core config intended for testing Kathy without secret access
export function getCoreConfigStub(environment: DeployEnvironment) {
export async function getCoreConfigStub(environment: DeployEnvironment) {
const environmentConfig = getEnvironmentConfig(environment);
// Don't fetch any secrets.
const registry = await environmentConfig.getRegistry(false);
const testnetConfigs = pick(
await registry.getMetadata(),
environmentConfig.supportedChainNames,
);
const multiProvider = new MultiProvider({
// Desired chains here. Key must have funds on these chains
...testnetConfigs,

@ -1,3 +1,5 @@
import { pick } from '@hyperlane-xyz/utils';
import { getArgs } from './agent-utils.js';
import { getEnvironmentConfig } from './core-utils.js';
@ -9,7 +11,15 @@ async function main() {
const environmentConfig = getEnvironmentConfig(args.environment);
console.log(JSON.stringify(environmentConfig.chainMetadataConfigs, null, 2));
// Intentionally do not include any secrets in the output
const registry = await environmentConfig.getRegistry(false);
const allMetadata = await registry.getMetadata();
const environmentMetadata = pick(
allMetadata,
environmentConfig.supportedChainNames,
);
console.log(JSON.stringify(environmentMetadata, null, 2));
}
main().catch((err) => {

@ -1,18 +1,39 @@
import { ethers } from 'ethers';
import { MultiProtocolProvider, ProviderType } from '@hyperlane-xyz/sdk';
import { objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import {
ChainMap,
MultiProtocolProvider,
ProviderType,
} from '@hyperlane-xyz/sdk';
import { mainnetConfigs } from '../config/environments/mainnet3/chains.js';
import { getCosmosChainGasPrice } from '../src/config/gas-oracle.js';
import {
GasPriceConfig,
getCosmosChainGasPrice,
} from '../src/config/gas-oracle.js';
import { getEnvironmentConfig } from './core-utils.js';
async function main() {
const allMetadatas = mainnetConfigs;
const environmentConfig = getEnvironmentConfig('mainnet3');
const mpp = await environmentConfig.getMultiProtocolProvider();
const prices: ChainMap<GasPriceConfig> = Object.fromEntries(
await Promise.all(
environmentConfig.supportedChainNames.map(async (chain) => [
chain,
await getGasPrice(mpp, chain),
]),
),
);
const mpp = new MultiProtocolProvider(allMetadatas);
console.log(JSON.stringify(prices, null, 2));
}
const prices = await promiseObjAll(
objMap(allMetadatas, async (chain, metadata) => {
async function getGasPrice(
mpp: MultiProtocolProvider,
chain: string,
): Promise<GasPriceConfig> {
const provider = mpp.getProvider(chain);
switch (provider.type) {
case ProviderType.EthersV5: {
@ -32,14 +53,13 @@ async function main() {
}
case ProviderType.SolanaWeb3:
// TODO get a reasonable value
return '0.001';
return {
amount: '0.001',
decimals: 9,
};
default:
throw new Error(`Unsupported provider type: ${provider.type}`);
}
}),
);
console.log(JSON.stringify(prices, null, 2));
}
main()

@ -1,11 +1,17 @@
import { objMap } from '@hyperlane-xyz/utils';
import { objMap, pick } from '@hyperlane-xyz/utils';
import { mainnetConfigs } from '../config/environments/mainnet3/chains.js';
import { getEnvironmentConfig } from './core-utils.js';
const CURRENCY = 'usd';
async function main() {
const metadata = mainnetConfigs;
const environmentConfig = getEnvironmentConfig('mainnet3');
const registry = await environmentConfig.getRegistry();
const metadata = pick(
await registry.getMetadata(),
environmentConfig.supportedChainNames,
);
const ids = objMap(
metadata,

@ -300,14 +300,14 @@ export async function getSecretAwsCredentials(agentConfig: AgentContextConfig) {
};
}
export async function getSecretRpcEndpoint(
export async function getSecretRpcEndpoints(
environment: string,
chainName: ChainName,
quorum = false,
multipleEndpoints = false,
): Promise<string[]> {
const secret = await fetchGCPSecret(
`${environment}-rpc-endpoint${quorum ? 's' : ''}-${chainName}`,
quorum,
`${environment}-rpc-endpoint${multipleEndpoints ? 's' : ''}-${chainName}`,
multipleEndpoints,
);
if (typeof secret != 'string' && !Array.isArray(secret)) {
throw Error(`Expected secret for ${chainName} rpc endpoint`);

@ -1,16 +1,21 @@
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
import { providers } from 'ethers';
import { IRegistry } from '@hyperlane-xyz/registry';
import {
ChainMap,
ChainMetadata,
ChainName,
HyperlaneSmartProvider,
ProviderRetryOptions,
RpcConsensusType,
RpcUrl,
} from '@hyperlane-xyz/sdk';
import { ProtocolType, objFilter } from '@hyperlane-xyz/utils';
import { ProtocolType, objFilter, objMerge } from '@hyperlane-xyz/utils';
import { getChain } from '../../config/registry.js';
import { getSecretRpcEndpoint } from '../agents/index.js';
import { getChain, getRegistryWithOverrides } from '../../config/registry.js';
import { getSecretRpcEndpoints } from '../agents/index.js';
import { inCIMode } from '../utils/utils.js';
import { DeployEnvironment } from './environment.js';
@ -20,7 +25,6 @@ export const defaultRetry: ProviderRetryOptions = {
};
export async function fetchProvider(
environment: DeployEnvironment,
chainName: ChainName,
connectionType: RpcConsensusType = RpcConsensusType.Single,
): Promise<providers.Provider> {
@ -29,10 +33,9 @@ export async function fetchProvider(
throw Error(`Unsupported chain: ${chainName}`);
}
const chainId = chainMetadata.chainId;
const single = connectionType === RpcConsensusType.Single;
let rpcData = chainMetadata.rpcUrls.map((url) => url.http);
if (rpcData.length === 0) {
rpcData = await getSecretRpcEndpoint(environment, chainName, !single);
throw Error(`No RPC URLs found for chain: ${chainName}`);
}
if (connectionType === RpcConsensusType.Single) {
@ -73,3 +76,69 @@ export function getChainMetadatas(chains: Array<ChainName>) {
return { ethereumMetadatas, nonEthereumMetadatas };
}
/**
* Gets the registry for the given environment, with optional overrides and
* the ability to get overrides from secrets.
* @param deployEnv The deploy environment.
* @param chains The chains to get metadata for.
* @param defaultChainMetadataOverrides The default chain metadata overrides. If
* secret overrides are used, the secret overrides will be merged with these and
* take precedence.
* @param useSecrets Whether to fetch metadata overrides from secrets.
* @returns A registry with overrides for the given environment.
*/
export async function getRegistryForEnvironment(
deployEnv: DeployEnvironment,
chains: ChainName[],
defaultChainMetadataOverrides: ChainMap<Partial<ChainMetadata>> = {},
useSecrets: boolean = true,
): Promise<IRegistry> {
let overrides = defaultChainMetadataOverrides;
if (useSecrets && !inCIMode()) {
overrides = objMerge(
overrides,
await getSecretMetadataOverrides(deployEnv, chains),
);
}
const registry = getRegistryWithOverrides(overrides);
return registry;
}
/**
* Gets chain metadata overrides from GCP secrets.
* @param deployEnv The deploy environment.
* @param chains The chains to get metadata overrides for.
* @returns A partial chain metadata map with the secret overrides.
*/
export async function getSecretMetadataOverrides(
deployEnv: DeployEnvironment,
chains: string[],
): Promise<ChainMap<Partial<ChainMetadata>>> {
const chainMetadataOverrides: ChainMap<Partial<ChainMetadata>> = {};
const secretRpcUrls = await Promise.all(
chains.map(async (chain) => {
const rpcUrls = await getSecretRpcEndpoints(deployEnv, chain, true);
return {
chain,
rpcUrls,
};
}),
);
for (const { chain, rpcUrls } of secretRpcUrls) {
if (rpcUrls.length === 0) {
throw Error(`No secret RPC URLs found for chain: ${chain}`);
}
// Need explicit casting here because Zod expects a non-empty array.
const metadataRpcUrls = rpcUrls.map((rpcUrl: string) => ({
http: rpcUrl,
})) as ChainMetadata['rpcUrls'];
chainMetadataOverrides[chain] = {
rpcUrls: metadataRpcUrls,
};
}
return chainMetadataOverrides;
}

@ -1,3 +1,4 @@
import { IRegistry } from '@hyperlane-xyz/registry';
import {
BridgeAdapterConfig,
ChainMap,
@ -5,6 +6,7 @@ import {
ChainName,
CoreConfig,
IgpConfig,
MultiProtocolProvider,
MultiProvider,
OwnableConfig,
RpcConsensusType,
@ -39,17 +41,21 @@ export const envNameToAgentEnv: Record<DeployEnvironment, AgentEnvironment> = {
export type EnvironmentConfig = {
environment: DeployEnvironment;
chainMetadataConfigs: ChainMap<ChainMetadata>;
supportedChainNames: ChainName[];
// Get the registry with or without environment-specific secrets.
getRegistry: (useSecrets?: boolean) => Promise<IRegistry>;
// Each AgentConfig, keyed by the context
agents: Partial<Record<Contexts, RootAgentConfig>>;
core: ChainMap<CoreConfig>;
igp: ChainMap<IgpConfig>;
owners: ChainMap<OwnableConfig>;
infra: InfrastructureConfig;
getMultiProtocolProvider: () => Promise<MultiProtocolProvider>;
getMultiProvider: (
context?: Contexts,
role?: Role,
connectionType?: RpcConsensusType,
useSecrets?: boolean,
) => Promise<MultiProvider>;
getKeys: (
context?: Contexts,

@ -1,3 +1,4 @@
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
import fs from 'fs';
import { rootLogger } from '@hyperlane-xyz/utils';
@ -6,6 +7,8 @@ import { rm, writeFile } from 'fs/promises';
import { execCmd, execCmdAndParseJson } from './utils.js';
export const GCP_PROJECT_ID = 'abacus-labs-dev';
interface IamCondition {
title: string;
expression: string;
@ -32,9 +35,7 @@ export async function fetchGCPSecret(
);
output = envVarOverride;
} else {
[output] = await execCmd(
`gcloud secrets versions access latest --secret ${secretName}`,
);
output = await fetchLatestGCPSecret(secretName);
}
if (parseJson) {
@ -43,6 +44,29 @@ export async function fetchGCPSecret(
return output;
}
export async function fetchLatestGCPSecret(secretName: string) {
const client = new SecretManagerServiceClient({
projectId: GCP_PROJECT_ID,
});
const [secretVersion] = await client.accessSecretVersion({
name: `projects/${GCP_PROJECT_ID}/secrets/${secretName}/versions/latest`,
});
const secretData = secretVersion.payload?.data;
if (!secretData) {
throw new Error(`Secret ${secretName} missing payload`);
}
// Handle both string and Uint8Array
let dataStr: string;
if (typeof secretData === 'string') {
dataStr = secretData;
} else {
dataStr = new TextDecoder().decode(secretData);
}
return dataStr;
}
// If the environment variable GCP_SECRET_OVERRIDES_ENABLED is `true`,
// this will attempt to find an environment variable of the form:
// `GCP_SECRET_OVERRIDE_${gcpSecretName.replaceAll('-', '_').toUpperCase()}`

@ -269,3 +269,7 @@ export function isEthereumProtocolChain(chainName: ChainName) {
export function getInfraPath() {
return join(dirname(fileURLToPath(import.meta.url)), '../../');
}
export function inCIMode() {
return process.env.CI === 'true';
}

@ -399,6 +399,16 @@ export function buildAgentConfig(
const chainConfigs: ChainMap<AgentChainMetadata> = {};
for (const chain of [...chains].sort()) {
const metadata = multiProvider.tryGetChainMetadata(chain);
if (metadata?.protocol === ProtocolType.Cosmos) {
// Note: the gRPC URL format in the registry lacks a correct http:// or https:// prefix at the moment,
// which is expected by the agents. For now, we intentionally skip this.
delete metadata.grpcUrls;
// The agents expect gasPrice.amount and gasPrice.denom and ignore the transaction overrides.
// To reduce confusion when looking at the config, we remove the transaction overrides.
delete metadata.transactionOverrides;
}
const chainConfig: AgentChainMetadata = {
...metadata,
...addresses[chain],

@ -5608,6 +5608,39 @@ __metadata:
languageName: node
linkType: hard
"@google-cloud/secret-manager@npm:^5.5.0":
version: 5.5.0
resolution: "@google-cloud/secret-manager@npm:5.5.0"
dependencies:
google-gax: "npm:^4.0.3"
checksum: 487267dab1e260a0da79012194bb61c85f8b02b642330fdec32cac1fe37900f0fd6709ff4928fe631ab227b0d758bd3e59b1e3dc1d0682de566a64ef4fb42bba
languageName: node
linkType: hard
"@grpc/grpc-js@npm:~1.10.3":
version: 1.10.8
resolution: "@grpc/grpc-js@npm:1.10.8"
dependencies:
"@grpc/proto-loader": "npm:^0.7.13"
"@js-sdsl/ordered-map": "npm:^4.4.2"
checksum: cb7903e93db38a86bd2ddffb84313de78144454ad988801ede90f0c794d6a5f666a1b24f50e950b50d633b4bacc7416c7cabf4a6791b91c4fa89c001122edba8
languageName: node
linkType: hard
"@grpc/proto-loader@npm:^0.7.0, @grpc/proto-loader@npm:^0.7.13":
version: 0.7.13
resolution: "@grpc/proto-loader@npm:0.7.13"
dependencies:
lodash.camelcase: "npm:^4.3.0"
long: "npm:^5.0.0"
protobufjs: "npm:^7.2.5"
yargs: "npm:^17.7.2"
bin:
proto-loader-gen-types: build/bin/proto-loader-gen-types.js
checksum: 7e2d842c2061cbaf6450c71da0077263be3bab165454d5c8a3e1ae4d3c6d2915f02fd27da63ff01f05e127b1221acd40705273f5d29303901e60514e852992f4
languageName: node
linkType: hard
"@headlessui/react@npm:^1.7.17":
version: 1.7.18
resolution: "@headlessui/react@npm:1.7.18"
@ -5824,6 +5857,7 @@ __metadata:
"@ethersproject/experimental": "npm:^5.7.0"
"@ethersproject/hardware-wallets": "npm:^5.7.0"
"@ethersproject/providers": "npm:^5.7.2"
"@google-cloud/secret-manager": "npm:^5.5.0"
"@hyperlane-xyz/helloworld": "npm:3.13.0"
"@hyperlane-xyz/registry": "npm:1.3.0"
"@hyperlane-xyz/sdk": "npm:3.13.0"
@ -6501,6 +6535,13 @@ __metadata:
languageName: node
linkType: hard
"@js-sdsl/ordered-map@npm:^4.4.2":
version: 4.4.2
resolution: "@js-sdsl/ordered-map@npm:4.4.2"
checksum: ac64e3f0615ecc015461c9f527f124d2edaa9e68de153c1e270c627e01e83d046522d7e872692fd57a8c514578b539afceff75831c0d8b2a9a7a347fbed35af4
languageName: node
linkType: hard
"@layerzerolabs/lz-evm-messagelib-v2@npm:^2.0.2":
version: 2.0.6
resolution: "@layerzerolabs/lz-evm-messagelib-v2@npm:2.0.6"
@ -9439,6 +9480,13 @@ __metadata:
languageName: node
linkType: hard
"@types/caseless@npm:*":
version: 0.12.5
resolution: "@types/caseless@npm:0.12.5"
checksum: f6a3628add76d27005495914c9c3873a93536957edaa5b69c63b46fe10b4649a6fecf16b676c1695f46aab851da47ec6047dcf3570fa8d9b6883492ff6d074e0
languageName: node
linkType: hard
"@types/chai@npm:*, @types/chai@npm:^4.2.21":
version: 4.3.1
resolution: "@types/chai@npm:4.3.1"
@ -9607,7 +9655,7 @@ __metadata:
languageName: node
linkType: hard
"@types/long@npm:^4.0.1":
"@types/long@npm:^4.0.0, @types/long@npm:^4.0.1":
version: 4.0.2
resolution: "@types/long@npm:4.0.2"
checksum: 68afa05fb20949d88345876148a76f6ccff5433310e720db51ac5ca21cb8cc6714286dbe04713840ddbd25a8b56b7a23aa87d08472fabf06463a6f2ed4967707
@ -9814,6 +9862,18 @@ __metadata:
languageName: node
linkType: hard
"@types/request@npm:^2.48.8":
version: 2.48.12
resolution: "@types/request@npm:2.48.12"
dependencies:
"@types/caseless": "npm:*"
"@types/node": "npm:*"
"@types/tough-cookie": "npm:*"
form-data: "npm:^2.5.0"
checksum: a7b3f9f14cacc18fe235bb8e57eff1232a04bd3fa3dad29371f24a5d96db2cd295a0c8b6b34ed7efa3efbbcff845febb02c9635cd68c54811c947ea66ae22090
languageName: node
linkType: hard
"@types/resolve@npm:^0.0.8":
version: 0.0.8
resolution: "@types/resolve@npm:0.0.8"
@ -9904,6 +9964,13 @@ __metadata:
languageName: node
linkType: hard
"@types/tough-cookie@npm:*":
version: 4.0.5
resolution: "@types/tough-cookie@npm:4.0.5"
checksum: 01fd82efc8202670865928629697b62fe9bf0c0dcbc5b1c115831caeb073a2c0abb871ff393d7df1ae94ea41e256cb87d2a5a91fd03cdb1b0b4384e08d4ee482
languageName: node
linkType: hard
"@types/trusted-types@npm:^2.0.2":
version: 2.0.7
resolution: "@types/trusted-types@npm:2.0.7"
@ -10902,6 +10969,15 @@ __metadata:
languageName: node
linkType: hard
"agent-base@npm:^7.0.2":
version: 7.1.1
resolution: "agent-base@npm:7.1.1"
dependencies:
debug: "npm:^4.3.4"
checksum: c478fec8f79953f118704d007a38f2a185458853f5c45579b9669372bd0e12602e88dc2ad0233077831504f7cd6fcc8251c383375bba5eaaf563b102938bda26
languageName: node
linkType: hard
"agentkeepalive@npm:^4.2.1":
version: 4.2.1
resolution: "agentkeepalive@npm:4.2.1"
@ -11956,6 +12032,13 @@ __metadata:
languageName: node
linkType: hard
"buffer-equal-constant-time@npm:1.0.1":
version: 1.0.1
resolution: "buffer-equal-constant-time@npm:1.0.1"
checksum: 80bb945f5d782a56f374b292770901065bad21420e34936ecbe949e57724b4a13874f735850dd1cc61f078773c4fb5493a41391e7bda40d1fa388d6bd80daaab
languageName: node
linkType: hard
"buffer-from@npm:^1.0.0":
version: 1.1.2
resolution: "buffer-from@npm:1.1.2"
@ -13651,6 +13734,18 @@ __metadata:
languageName: node
linkType: hard
"duplexify@npm:^4.0.0":
version: 4.1.3
resolution: "duplexify@npm:4.1.3"
dependencies:
end-of-stream: "npm:^1.4.1"
inherits: "npm:^2.0.3"
readable-stream: "npm:^3.1.1"
stream-shift: "npm:^1.0.2"
checksum: b44b98ba0ffac3a658b4b1bf877219e996db288c5ae6f3dc55ca9b2cbef7df60c10eabfdd947f3d73a623eb9975a74a66d6d61e6f26bff90155315adb362aa77
languageName: node
linkType: hard
"duplexify@npm:^4.1.2":
version: 4.1.2
resolution: "duplexify@npm:4.1.2"
@ -13680,6 +13775,15 @@ __metadata:
languageName: node
linkType: hard
"ecdsa-sig-formatter@npm:1.0.11, ecdsa-sig-formatter@npm:^1.0.11":
version: 1.0.11
resolution: "ecdsa-sig-formatter@npm:1.0.11"
dependencies:
safe-buffer: "npm:^5.0.1"
checksum: 878e1aab8a42773320bc04c6de420bee21aebd71810e40b1799880a8a1c4594bcd6adc3d4213a0fb8147d4c3f529d8f9a618d7f59ad5a9a41b142058aceda23f
languageName: node
linkType: hard
"ee-first@npm:1.1.1":
version: 1.1.1
resolution: "ee-first@npm:1.1.1"
@ -14912,7 +15016,7 @@ __metadata:
languageName: node
linkType: hard
"extend@npm:~3.0.2":
"extend@npm:^3.0.2, extend@npm:~3.0.2":
version: 3.0.2
resolution: "extend@npm:3.0.2"
checksum: 59e89e2dc798ec0f54b36d82f32a27d5f6472c53974f61ca098db5d4648430b725387b53449a34df38fd0392045434426b012f302b3cc049a6500ccf82877e4e
@ -15303,7 +15407,7 @@ __metadata:
languageName: node
linkType: hard
"form-data@npm:^2.2.0":
"form-data@npm:^2.2.0, form-data@npm:^2.5.0":
version: 2.5.1
resolution: "form-data@npm:2.5.1"
dependencies:
@ -15666,6 +15770,29 @@ __metadata:
languageName: node
linkType: hard
"gaxios@npm:^6.0.0, gaxios@npm:^6.1.1":
version: 6.6.0
resolution: "gaxios@npm:6.6.0"
dependencies:
extend: "npm:^3.0.2"
https-proxy-agent: "npm:^7.0.1"
is-stream: "npm:^2.0.0"
node-fetch: "npm:^2.6.9"
uuid: "npm:^9.0.1"
checksum: 9f035590374fd168e7bb3ddda369fc8bd487f16a2308fde18284ccc0f685d0af4ac5e3e38d680a8c6342a9000fbf9d77ce691ee110dbed2feebb659e729c640a
languageName: node
linkType: hard
"gcp-metadata@npm:^6.1.0":
version: 6.1.0
resolution: "gcp-metadata@npm:6.1.0"
dependencies:
gaxios: "npm:^6.0.0"
json-bigint: "npm:^1.0.0"
checksum: a0d12a9cb7499fdb9de0fff5406aa220310c1326b80056be8d9b747aae26414f99d14bd795c0ec52ef7d0473eef9d61bb657b8cd3d8186c8a84c4ddbff025fe9
languageName: node
linkType: hard
"gensync@npm:^1.0.0-beta.2":
version: 1.0.0-beta.2
resolution: "gensync@npm:1.0.0-beta.2"
@ -16034,6 +16161,40 @@ __metadata:
languageName: node
linkType: hard
"google-auth-library@npm:^9.3.0":
version: 9.10.0
resolution: "google-auth-library@npm:9.10.0"
dependencies:
base64-js: "npm:^1.3.0"
ecdsa-sig-formatter: "npm:^1.0.11"
gaxios: "npm:^6.1.1"
gcp-metadata: "npm:^6.1.0"
gtoken: "npm:^7.0.0"
jws: "npm:^4.0.0"
checksum: 10d5863493f9426107b0f6c4df244b1413a2cacff9589076f906924336d894fe8bc4153d4a3756cebec8a58784ff1a3900c621924f75f004908611fa46d3caa6
languageName: node
linkType: hard
"google-gax@npm:^4.0.3":
version: 4.3.3
resolution: "google-gax@npm:4.3.3"
dependencies:
"@grpc/grpc-js": "npm:~1.10.3"
"@grpc/proto-loader": "npm:^0.7.0"
"@types/long": "npm:^4.0.0"
abort-controller: "npm:^3.0.0"
duplexify: "npm:^4.0.0"
google-auth-library: "npm:^9.3.0"
node-fetch: "npm:^2.6.1"
object-hash: "npm:^3.0.0"
proto3-json-serializer: "npm:^2.0.0"
protobufjs: "npm:7.2.6"
retry-request: "npm:^7.0.0"
uuid: "npm:^9.0.1"
checksum: 63335724e741737b90689e43f8ea5804d82b8f4eaa013ba07166bf6119ef7474d06682d580d72f6b708d6c55251204b1f05db615c3cd84abf2f8f295c50882ec
languageName: node
linkType: hard
"gopd@npm:^1.0.1":
version: 1.0.1
resolution: "gopd@npm:1.0.1"
@ -16166,6 +16327,16 @@ __metadata:
languageName: node
linkType: hard
"gtoken@npm:^7.0.0":
version: 7.1.0
resolution: "gtoken@npm:7.1.0"
dependencies:
gaxios: "npm:^6.0.0"
jws: "npm:^4.0.0"
checksum: 640392261e55c9242137a81a4af8feb053b57061762cedddcbb6a0d62c2314316161808ac2529eea67d06d69fdc56d82361af50f2d840a04a87ea29e124d7382
languageName: node
linkType: hard
"h3@npm:^1.10.1, h3@npm:^1.8.2":
version: 1.10.2
resolution: "h3@npm:1.10.2"
@ -16725,6 +16896,16 @@ __metadata:
languageName: node
linkType: hard
"https-proxy-agent@npm:^7.0.1":
version: 7.0.4
resolution: "https-proxy-agent@npm:7.0.4"
dependencies:
agent-base: "npm:^7.0.2"
debug: "npm:4"
checksum: 405fe582bba461bfe5c7e2f8d752b384036854488b828ae6df6a587c654299cbb2c50df38c4b6ab303502c3c5e029a793fbaac965d1e86ee0be03faceb554d63
languageName: node
linkType: hard
"human-id@npm:^1.0.2":
version: 1.0.2
resolution: "human-id@npm:1.0.2"
@ -18336,6 +18517,27 @@ __metadata:
languageName: node
linkType: hard
"jwa@npm:^2.0.0":
version: 2.0.0
resolution: "jwa@npm:2.0.0"
dependencies:
buffer-equal-constant-time: "npm:1.0.1"
ecdsa-sig-formatter: "npm:1.0.11"
safe-buffer: "npm:^5.0.1"
checksum: ab983f6685d99d13ddfbffef9b1c66309a536362a8412d49ba6e687d834a1240ce39290f30ac7dbe241e0ab6c76fee7ff795776ce534e11d148158c9b7193498
languageName: node
linkType: hard
"jws@npm:^4.0.0":
version: 4.0.0
resolution: "jws@npm:4.0.0"
dependencies:
jwa: "npm:^2.0.0"
safe-buffer: "npm:^5.0.1"
checksum: 1d15f4cdea376c6bd6a81002bd2cb0bf3d51d83da8f0727947b5ba3e10cf366721b8c0d099bf8c1eb99eb036e2c55e5fd5efd378ccff75a2b4e0bd10002348b9
languageName: node
linkType: hard
"keccak@npm:3.0.1":
version: 3.0.1
resolution: "keccak@npm:3.0.1"
@ -18918,6 +19120,13 @@ __metadata:
languageName: node
linkType: hard
"long@npm:^5.0.0":
version: 5.2.3
resolution: "long@npm:5.2.3"
checksum: 9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6
languageName: node
linkType: hard
"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"
@ -20113,7 +20322,7 @@ __metadata:
languageName: node
linkType: hard
"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12":
"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.9":
version: 2.7.0
resolution: "node-fetch@npm:2.7.0"
dependencies:
@ -20422,6 +20631,13 @@ __metadata:
languageName: node
linkType: hard
"object-hash@npm:^3.0.0":
version: 3.0.0
resolution: "object-hash@npm:3.0.0"
checksum: f498d456a20512ba7be500cef4cf7b3c183cc72c65372a549c9a0e6dd78ce26f375e9b1315c07592d3fde8f10d5019986eba35970570d477ed9a2a702514432a
languageName: node
linkType: hard
"object-inspect@npm:^1.12.0, object-inspect@npm:^1.12.2, object-inspect@npm:^1.9.0":
version: 1.12.2
resolution: "object-inspect@npm:1.12.2"
@ -21344,6 +21560,35 @@ __metadata:
languageName: node
linkType: hard
"proto3-json-serializer@npm:^2.0.0":
version: 2.0.1
resolution: "proto3-json-serializer@npm:2.0.1"
dependencies:
protobufjs: "npm:^7.2.5"
checksum: dc4319c90e2412b9647f13dd1df2a6338ee3a07e2fd693c5ce4d1728c3730d913ebdb6d656f400ae4214a70bf0791ca0bc04d53b2cbdd75394bf0b175898443b
languageName: node
linkType: hard
"protobufjs@npm:7.2.6":
version: 7.2.6
resolution: "protobufjs@npm:7.2.6"
dependencies:
"@protobufjs/aspromise": "npm:^1.1.2"
"@protobufjs/base64": "npm:^1.1.2"
"@protobufjs/codegen": "npm:^2.0.4"
"@protobufjs/eventemitter": "npm:^1.1.0"
"@protobufjs/fetch": "npm:^1.1.0"
"@protobufjs/float": "npm:^1.0.2"
"@protobufjs/inquire": "npm:^1.1.0"
"@protobufjs/path": "npm:^1.1.2"
"@protobufjs/pool": "npm:^1.1.0"
"@protobufjs/utf8": "npm:^1.1.0"
"@types/node": "npm:>=13.7.0"
long: "npm:^5.0.0"
checksum: 81ab853d28c71998d056d6b34f83c4bc5be40cb0b416585f99ed618aed833d64b2cf89359bad7474d345302f2b5e236c4519165f8483d7ece7fd5b0d9ac13f8b
languageName: node
linkType: hard
"protobufjs@npm:^6.8.8, protobufjs@npm:~6.11.2, protobufjs@npm:~6.11.3":
version: 6.11.4
resolution: "protobufjs@npm:6.11.4"
@ -21368,6 +21613,26 @@ __metadata:
languageName: node
linkType: hard
"protobufjs@npm:^7.2.5":
version: 7.3.0
resolution: "protobufjs@npm:7.3.0"
dependencies:
"@protobufjs/aspromise": "npm:^1.1.2"
"@protobufjs/base64": "npm:^1.1.2"
"@protobufjs/codegen": "npm:^2.0.4"
"@protobufjs/eventemitter": "npm:^1.1.0"
"@protobufjs/fetch": "npm:^1.1.0"
"@protobufjs/float": "npm:^1.0.2"
"@protobufjs/inquire": "npm:^1.1.0"
"@protobufjs/path": "npm:^1.1.2"
"@protobufjs/pool": "npm:^1.1.0"
"@protobufjs/utf8": "npm:^1.1.0"
"@types/node": "npm:>=13.7.0"
long: "npm:^5.0.0"
checksum: aff4aa2a3a2f011accb51e23fcae122acbee35cb761abe51f799675a61ab39ad9a506911f307e0fdb9a1703bed1f522cfbdaafaeefd2b3aaca2ddc18f03029d9
languageName: node
linkType: hard
"proxy-addr@npm:~2.0.7":
version: 2.0.7
resolution: "proxy-addr@npm:2.0.7"
@ -22253,6 +22518,17 @@ __metadata:
languageName: node
linkType: hard
"retry-request@npm:^7.0.0":
version: 7.0.2
resolution: "retry-request@npm:7.0.2"
dependencies:
"@types/request": "npm:^2.48.8"
extend: "npm:^3.0.2"
teeny-request: "npm:^9.0.0"
checksum: 8f4c927d41dd575fc460aad7b762fb0a33542097201c3c1a31529ad17fa8af3ac0d2a45bf4a2024d079913e9c2dd431566070fe33321c667ac87ebb400de5917
languageName: node
linkType: hard
"retry@npm:0.13.1":
version: 0.13.1
resolution: "retry@npm:0.13.1"
@ -23390,7 +23666,16 @@ __metadata:
languageName: node
linkType: hard
"stream-shift@npm:^1.0.0":
"stream-events@npm:^1.0.5":
version: 1.0.5
resolution: "stream-events@npm:1.0.5"
dependencies:
stubs: "npm:^3.0.0"
checksum: 969ce82e34bfbef5734629cc06f9d7f3705a9ceb8fcd6a526332f9159f1f8bbfdb1a453f3ced0b728083454f7706adbbe8428bceb788a0287ca48ba2642dc3fc
languageName: node
linkType: hard
"stream-shift@npm:^1.0.0, stream-shift@npm:^1.0.2":
version: 1.0.3
resolution: "stream-shift@npm:1.0.3"
checksum: a24c0a3f66a8f9024bd1d579a533a53be283b4475d4e6b4b3211b964031447bdf6532dd1f3c2b0ad66752554391b7c62bd7ca4559193381f766534e723d50242
@ -23690,6 +23975,13 @@ __metadata:
languageName: node
linkType: hard
"stubs@npm:^3.0.0":
version: 3.0.0
resolution: "stubs@npm:3.0.0"
checksum: dec7b82186e3743317616235c59bfb53284acc312cb9f4c3e97e2205c67a5c158b0ca89db5927e52351582e90a2672822eeaec9db396e23e56893d2a8676e024
languageName: node
linkType: hard
"styled-jsx@npm:5.1.1":
version: 5.1.1
resolution: "styled-jsx@npm:5.1.1"
@ -23943,6 +24235,19 @@ __metadata:
languageName: node
linkType: hard
"teeny-request@npm:^9.0.0":
version: 9.0.0
resolution: "teeny-request@npm:9.0.0"
dependencies:
http-proxy-agent: "npm:^5.0.0"
https-proxy-agent: "npm:^5.0.0"
node-fetch: "npm:^2.6.9"
stream-events: "npm:^1.0.5"
uuid: "npm:^9.0.0"
checksum: 44daabb6c2e239c3daed0218ebdafb50c7141c16d7257a6cfef786dbff56d7853c2c02c97934f7ed57818ce5861ac16c5f52f3a16fa292bd4caf53483d386443
languageName: node
linkType: hard
"term-size@npm:^2.1.0":
version: 2.2.1
resolution: "term-size@npm:2.2.1"

Loading…
Cancel
Save