UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

73 lines 3.65 kB
import { OperationType, } from '@safe-global/safe-core-sdk-types'; import { assert, rootLogger } from '@hyperlane-xyz/utils'; // prettier-ignore // @ts-ignore import { canProposeSafeTransactions, getSafe, getSafeService } from '../../../../utils/gnosisSafe.js'; import { TxSubmitterType } from '../TxSubmitterTypes.js'; export class EV5GnosisSafeTxSubmitter { multiProvider; props; safe; safeService; txSubmitterType = TxSubmitterType.GNOSIS_SAFE; logger = rootLogger.child({ module: 'gnosis-safe-submitter', }); constructor(multiProvider, props, safe, safeService) { this.multiProvider = multiProvider; this.props = props; this.safe = safe; this.safeService = safeService; } static async create(multiProvider, props) { const { chain, safeAddress } = props; const { gnosisSafeTransactionServiceUrl } = multiProvider.getChainMetadata(chain); assert(gnosisSafeTransactionServiceUrl, `Must set gnosisSafeTransactionServiceUrl in the Registry metadata for ${chain}`); const signerAddress = await multiProvider.getSigner(chain).getAddress(); const authorized = await canProposeSafeTransactions(signerAddress, chain, multiProvider, safeAddress); assert(authorized, `Signer ${signerAddress} is not an authorized Safe Proposer for ${safeAddress}`); const safe = await getSafe(chain, multiProvider, safeAddress); const safeService = await getSafeService(chain, multiProvider); return new EV5GnosisSafeTxSubmitter(multiProvider, props, safe, safeService); } async createSafeTransaction(...transactions) { const nextNonce = await this.safeService.getNextNonce(this.props.safeAddress); const submitterChainId = this.multiProvider.getChainId(this.props.chain); const safeTransactionData = transactions.map(({ to, data, value, chainId }) => { assert(chainId, 'Invalid AnnotatedEV5Transaction: chainId is required'); assert(chainId === submitterChainId, `Invalid AnnotatedEV5Transaction: Cannot submit tx for chain ID ${chainId} to submitter for chain ID ${submitterChainId}.`); return { to, data, value: value?.toString() ?? '0' }; }); const isMultiSend = transactions.length > 1; const safeTransaction = await this.safe.createTransaction({ safeTransactionData, onlyCalls: isMultiSend, options: { nonce: nextNonce, operation: isMultiSend ? OperationType.DelegateCall : OperationType.Call, }, }); return safeTransaction; } async submit(...txs) { const safeTransaction = await this.createSafeTransaction(...txs); return this.proposeSafeTransaction(safeTransaction); } async proposeSafeTransaction(safeTransaction) { const safeTxHash = await this.safe.getTransactionHash(safeTransaction); const senderAddress = await this.multiProvider.getSignerAddress(this.props.chain); const safeSignature = await this.safe.signTypedData(safeTransaction); const senderSignature = safeSignature.data; this.logger.info(`Submitting transaction proposal to ${this.props.safeAddress} on ${this.props.chain}: ${safeTxHash}`); return this.safeService.proposeTransaction({ safeAddress: this.props.safeAddress, safeTransactionData: safeTransaction.data, safeTxHash, senderAddress, senderSignature, }); } } //# sourceMappingURL=EV5GnosisSafeTxSubmitter.js.map