UNPKG

cosmic-interchain-cli

Version:

A command-line utility for Cosmic Wire's interchain messaging protocol

64 lines 4.03 kB
import { password } from '@inquirer/prompts'; import { Wallet, utils } from 'ethers'; import { ECDSAStakeRegistry__factory, TestAVSDirectory__factory, } from '@hyperlane-xyz/core'; import { log, logBlue } from '../logger.js'; import { readFileAtPath, resolvePath } from '../utils/files.js'; import { avsAddresses } from './config.js'; export async function registerOperatorWithSignature({ context, chain, operatorKeyPath, avsSigningKeyAddress, }) { const { multiProvider } = context; const operatorAsSigner = await readOperatorFromEncryptedJson(operatorKeyPath); const provider = multiProvider.getProvider(chain); const connectedSigner = operatorAsSigner.connect(provider); const stakeRegistryAddress = avsAddresses[chain].ecdsaStakeRegistry; const ecdsaStakeRegistry = ECDSAStakeRegistry__factory.connect(stakeRegistryAddress, connectedSigner); const domainId = multiProvider.getDomainId(chain); const avsDirectoryAddress = avsAddresses[chain].avsDirectory; const operatorSignature = await getOperatorSignature(domainId, avsAddresses[chain].hyperlaneServiceManager, avsDirectoryAddress, operatorAsSigner, connectedSigner); // check if the operator is already registered const operatorStatus = await ecdsaStakeRegistry.operatorRegistered(operatorAsSigner.address); if (operatorStatus) { logBlue(`Operator ${operatorAsSigner.address} already registered to Hyperlane AVS`); return; } log(`Registering operator ${operatorAsSigner.address} attesting ${avsSigningKeyAddress} with signature on ${chain}...`); await multiProvider.handleTx(chain, ecdsaStakeRegistry.registerOperatorWithSignature(operatorSignature, avsSigningKeyAddress)); logBlue(`Operator ${operatorAsSigner.address} registered to Hyperlane AVS`); } export async function deregisterOperator({ context, chain, operatorKeyPath, }) { const { multiProvider } = context; const operatorAsSigner = await readOperatorFromEncryptedJson(operatorKeyPath); const provider = multiProvider.getProvider(chain); const connectedSigner = operatorAsSigner.connect(provider); const stakeRegistryAddress = avsAddresses[chain].ecdsaStakeRegistry; const ecdsaStakeRegistry = ECDSAStakeRegistry__factory.connect(stakeRegistryAddress, connectedSigner); log(`Deregistering operator ${operatorAsSigner.address} on ${chain}...`); await multiProvider.handleTx(chain, ecdsaStakeRegistry.deregisterOperator()); logBlue(`Operator ${operatorAsSigner.address} deregistered from Hyperlane AVS`); } export async function readOperatorFromEncryptedJson(operatorKeyPath) { const encryptedJson = readFileAtPath(resolvePath(operatorKeyPath)); const keyFilePassword = await password({ mask: '*', message: 'Enter the password for the operator key file: ', }); return Wallet.fromEncryptedJson(encryptedJson, keyFilePassword); } async function getOperatorSignature(domain, serviceManager, avsDirectory, operator, signer) { const avsDirectoryContract = TestAVSDirectory__factory.connect(avsDirectory, signer); // random salt is ok, because we register the operator right after const salt = utils.hexZeroPad(utils.randomBytes(32), 32); // give a expiry timestamp 1 hour from now const expiry = utils.hexZeroPad(utils.hexlify(Math.floor(Date.now() / 1000) + 60 * 60), 32); const signingHash = await avsDirectoryContract.calculateOperatorAVSRegistrationDigestHash(operator.address, serviceManager, salt, expiry); // Eigenlayer's AVSDirectory expects the signature over raw signed hash instead of EIP-191 compatible toEthSignedMessageHash // see https://github.com/Layr-Labs/eigenlayer-contracts/blob/ef2ea4a7459884f381057aa9bbcd29c7148cfb63/src/contracts/libraries/EIP1271SignatureUtils.sol#L22 const signature = operator ._signingKey() .signDigest(utils.arrayify(signingHash)); return { signature: utils.joinSignature(signature), salt, expiry, }; } //# sourceMappingURL=stakeRegistry.js.map