import { ensureLeading0x } from '@celo/utils/src/address' ; import { DynamicEnvVar , envVar , fetchEnv } from 'src/lib/env-utils' ; import yargs from 'yargs' ; import { getCloudProviderFromContext , getDynamicEnvVarValues } from './context-utils' ; import { getOraclePrivateKeysFor , privateKeyToAddress } from './generate_utils' ; import { AksClusterConfig } from './k8s-cluster/aks' ; import { AwsClusterConfig } from './k8s-cluster/aws' ; import { BaseClusterManager , CloudProvider } from './k8s-cluster/base' ; import { AksHsmOracleDeployer , AksHsmOracleDeploymentConfig , AksHsmOracleIdentity , } from './k8s-oracle/aks-hsm' ; import { AwsHsmOracleDeployer , AwsHsmOracleDeploymentConfig , AwsHsmOracleIdentity , } from './k8s-oracle/aws-hsm' ; import { BaseOracleDeployer , CurrencyPair } from './k8s-oracle/base' ; import { PrivateKeyOracleDeployer , PrivateKeyOracleDeploymentConfig , PrivateKeyOracleIdentity , } from './k8s-oracle/pkey' ; /**
 * Maps each cloud provider to the correct function to get the appropriate
 * HSM-based oracle deployer.
 */ const hsmOracleDeployerGetterByCloudProvider = { [ CloudProvider . AWS ] : getAwsHsmOracleDeployer , [ CloudProvider . AZURE ] : getAksHsmOracleDeployer , } ; /**
 * Gets the appropriate oracle deployer for the given context. If the env vars
 * specify that the oracle addresses should be generated from the mnemonic,
 * then the cloud-provider agnostic deployer PrivateKeyOracleDeployer is used.
 */ export function getOracleDeployerForContext ( celoEnv , context , currencyPair , useForno , clusterManager ) { const { addressesFromMnemonicCount } = getDynamicEnvVarValues ( mnemonicBasedOracleIdentityConfigDynamicEnvVars , { context , currencyPair } , { addressesFromMnemonicCount : '' , } ) ; if ( addressesFromMnemonicCount ) { const addressesFromMnemonicCountNum = parseInt ( addressesFromMnemonicCount , 10 ) ; return getPrivateKeyOracleDeployer ( celoEnv , context , currencyPair , useForno , addressesFromMnemonicCountNum ) ; } const cloudProvider = getCloudProviderFromContext ( context ) ; const getDeployer = hsmOracleDeployerGetterByCloudProvider [ cloudProvider ] ; if ( getDeployer === undefined ) { throw new Error ( `Deployer not defined for CloudProvider: ${ cloudProvider }. ` + `Expecting one of: ${ Object . keys ( hsmOracleDeployerGetterByCloudProvider ) }` ) ; } return getDeployer ( celoEnv , context , currencyPair , useForno , clusterManager ) ; } /**
 * ----------- AksHsmOracleDeployer helpers -----------
 */ /**
 * Gets an AksHsmOracleDeployer by looking at env var values
 */ function getAksHsmOracleDeployer ( celoEnv , context , currencyPair , useForno , clusterManager ) { const { addressKeyVaults } = getDynamicEnvVarValues ( aksHsmOracleIdentityConfigDynamicEnvVars , { context , currencyPair } , { addressKeyVaults : '' , } ) ; const aksClusterConfig = clusterManager . clusterConfig as AksClusterConfig ; const identities = getAksHsmOracleIdentities ( addressKeyVaults , aksClusterConfig . resourceGroup , currencyPair ) ; const deploymentConfig = { context , clusterConfig : aksClusterConfig , currencyPair , identities , useForno , } ; return new AksHsmOracleDeployer ( deploymentConfig , celoEnv ) ; } /**
 * Given a string addressAzureKeyVaults containing comma separated info of the form:
 * <address>:<keyVaultName>:<resourceGroup (optional)>
 * eg: 0x0000000000000000000000000000000000000000:keyVault0,0x0000000000000000000000000000000000000001:keyVault1:resourceGroup1
 * returns an array of AksHsmOracleIdentity in the same order
 */ export function getAksHsmOracleIdentities ( addressAzureKeyVaults , defaultResourceGroup , currencyPair ) { const identityStrings = addressAzureKeyVaults . split ( ',' ) ; const identities = [ ] ; for ( const identityStr of identityStrings ) { const [ address , keyVaultName , resourceGroup ] = identityStr . split ( ':' ) ; if ( ! address || ! keyVaultName ) { throw Error ( `Address or key vault name is invalid. Address: ${ address } Key Vault Name: ${ keyVaultName }` ) ; } identities . push ( { address , currencyPair , keyVaultName , resourceGroup : resourceGroup || defaultResourceGroup , } ) ; } return identities ; } /**
 * Config values pulled from env vars used for generating an AksHsmOracleIdentity
 */ interface AksHsmOracleIdentityConfig { addressKeyVaults : string ; } /**
 * Env vars corresponding to each value for the AksHsmOracleIdentityConfig for a particular context
 */ const aksHsmOracleIdentityConfigDynamicEnvVars = { addressKeyVaults : DynamicEnvVar . ORACLE_ADDRESS_AZURE_KEY_VAULTS , } ; /**
 * ----------- AwsHsmOracleDeployer helpers -----------
 */ /**
 * Gets an AwsHsmOracleDeployer by looking at env var values
 */ function getAwsHsmOracleDeployer ( celoEnv , context , currencyPair , useForno , clusterManager ) { const { addressKeyAliases } = getDynamicEnvVarValues ( awsHsmOracleIdentityConfigDynamicEnvVars , { context , currencyPair } , { addressKeyAliases : '' , } ) ; const identities = getAwsHsmOracleIdentities ( addressKeyAliases , currencyPair ) ; const deploymentConfig = { context , clusterConfig : clusterManager . clusterConfig as AwsClusterConfig , currencyPair , identities , useForno , } ; return new AwsHsmOracleDeployer ( deploymentConfig , celoEnv ) ; } /**
 * Given a string addressKeyAliases containing comma separated info of the form:
 * <address>:<keyAlias>:<region (optional)>
 * eg: 0x0000000000000000000000000000000000000000:keyAlias0,0x0000000000000000000000000000000000000001:keyAlias1:region1
 * returns an array of AwsHsmOracleIdentity in the same order
 */ export function getAwsHsmOracleIdentities ( addressKeyAliases , currencyPair ) { const identityStrings = addressKeyAliases . split ( ',' ) ; const identities = [ ] ; for ( const identityStr of identityStrings ) { const [ address , keyAlias , region ] = identityStr . split ( ':' ) ; if ( ! address || ! keyAlias ) { throw Error ( `Address or key alias is invalid. Address: ${ address } Key Alias: ${ keyAlias }` ) ; } identities . push ( { address , currencyPair , keyAlias , region , } ) ; } return identities ; } /**
 * Config values pulled from env vars used for generating an AwsHsmOracleIdentity
 */ interface AwsHsmOracleIdentityConfig { addressKeyAliases : string ; } /**
 * Env vars corresponding to each value for the AwsHsmOracleIdentityConfig for a particular context
 */ const awsHsmOracleIdentityConfigDynamicEnvVars = { addressKeyAliases : DynamicEnvVar . ORACLE_ADDRESS_AWS_KEY_ALIASES , } ; /**
 * ----------- PrivateKeyOracleDeployer helpers -----------
 */ /**
 * Gets an AwsHsmOracleDeployer by looking at env var values and generating private keys
 * from the mnemonic
 */ function getPrivateKeyOracleDeployer ( celoEnv , context , currencyPair , useForno , count ) { const identities = getOraclePrivateKeysFor ( currencyPair , fetchEnv ( envVar . MNEMONIC ) , count ) . map ( ( pkey ) => ( { address : privateKeyToAddress ( pkey ) , currencyPair , privateKey : ensureLeading0x ( pkey ) , } ) ) ; const deploymentConfig = { context , currencyPair , identities , useForno , } ; return new PrivateKeyOracleDeployer ( deploymentConfig , celoEnv ) ; } /**
 * Config values pulled from env vars used for generating a PrivateKeyOracleIdentity
 * from a mnemonic
 */ interface MnemonicBasedOracleIdentityConfig { addressesFromMnemonicCount : string ; } /**
 * Env vars corresponding to each value for the MnemonicBasedOracleIdentityConfig for a particular context
 */ const mnemonicBasedOracleIdentityConfigDynamicEnvVars = { addressesFromMnemonicCount : DynamicEnvVar . ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT , } ; param argv export function addCurrencyPairMiddleware ( argv ) { return argv . option ( 'currencyPair' , { choices : [ 'CELOUSD' , 'CELOEUR' , 'CELOBRL' , 'CELOBTC' ] , description : 'Oracle deployment to target based on currency pair' , demandOption : true , type : 'string' , } ) ; } param argv export function addUseFornoMiddleware ( argv ) { return argv . option ( 'useForno' , { description : 'Uses forno for RPCs from the oracle clients' , default : false , type : 'boolean' , } ) ; }