feat(cli): add submit command (#3818)
### Description * adds `hyperlane submit -t ./transactions.json -s ./strategy.json` * given a set of `transactions` and a submission `strategy`, submit those transactions according to that strategy * example strategies provided under `/cli/examples/submit/` * detailed design: https://www.notion.so/hyperlanexyz/CLI-Submitter-Integration-8a14486803ca4ab18f229e8e7f89b57a?pvs=4 ### Drive-by changes * none ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3740 ### Backward compatibility - yes ### Testing #### Nice to have: - [ ] ci-test #### Manual: - [x] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/json-rpc-strategy.yaml` ``` Hyperlane Submit ---------------- Submitting 1 transactions to the jsonRpc submitter... Sent tx 0x7158756345a913630497dac948a98b1c73921626f9c17cc936994ff22dcd908f Pending https://alfajores.celoscan.io/tx/0x7158756345a913630497dac948a98b1c73921626f9c17cc936994ff22dcd908f (waiting 1 blocks for confirmation) ✅ Successfully submitted 1 transactions to the jsonRpc submitter. 🧾 Transaction receipts: [ { to: '0x9a4a3124F2a86bB5BE46267De85D31762b7a05Fd', from: '0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb', contractAddress: null, transactionIndex: 4, gasUsed: BigNumber { _hex: '0x53b8', _isBigNumber: true }, logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', blockHash: '0x174c3355800d73e3ab9643257bf49a60fc539a6961fc6cc8adcfb27d84ab6347', transactionHash: '0x7158756345a913630497dac948a98b1c73921626f9c17cc936994ff22dcd908f', logs: [], blockNumber: 24221122, confirmations: 1, cumulativeGasUsed: BigNumber { _hex: '0x072f3f', _isBigNumber: true }, effectiveGasPrice: BigNumber { _hex: '0x01836e2100', _isBigNumber: true }, status: 1, type: 2, byzantium: true } ] ✅ Hyperlane submission complete ``` - [x] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/json-rpc-strategy.yaml --dry-run` ``` ... Dry-running against chain: alfajores 🔎 Verifying anvil node is running... ✅ Successfully verified anvil node is running Forking alfajores for dry-run... ✅ Successfully forked alfajores for dry-run Impersonating account (0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb)... ✅ Successfully impersonated account (0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb) Hyperlane Submit ---------------- Submitting 1 transactions to the jsonRpc submitter... Sent tx 0x89fbd7d38d6fc19df0ef24f844756153dece1e0f179b76b036c50596356dc5ce Pending https://alfajores.celoscan.io/tx/0x89fbd7d38d6fc19df0ef24f844756153dece1e0f179b76b036c50596356dc5ce (waiting 1 blocks for confirmation) ✅ Successfully submitted 1 transactions to the jsonRpc submitter. 🧾 Transaction receipts: [ { to: '0x9a4a3124F2a86bB5BE46267De85D31762b7a05Fd', from: '0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb', contractAddress: null, transactionIndex: 0, gasUsed: BigNumber { _hex: '0x53b8', _isBigNumber: true }, logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', blockHash: '0x5a5379771a3a6d173a8dcbfc189e24f288c30abcd0a754f1df4734f465917cc7', transactionHash: '0x89fbd7d38d6fc19df0ef24f844756153dece1e0f179b76b036c50596356dc5ce', logs: [], blockNumber: 24221165, confirmations: 1, cumulativeGasUsed: BigNumber { _hex: '0x53b8', _isBigNumber: true }, effectiveGasPrice: BigNumber { _hex: '0x0104fd914d', _isBigNumber: true }, status: 1, type: 2, byzantium: true } ] ✅ Hyperlane submission complete ``` - [x] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/impersonated-account-strategy.yaml` - [x] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/impersonated-account-strategy.yaml --dry-run` - `Error: Impersonated account submitters may only be used during dry-runs.` - [x] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/gnosis-strategy.yaml` - Successfully generated proposal: https://app.safe.global/transactions/queue?safe=avax:0x7fd32493Ca3A38cDf78A4cb74F32f6292f822aBe - [ ] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/gnosis-ica-strategy.yaml` - [ ] `hl submit -t ./examples/submit/transactions/transactions.json -s ./examples/submit/strategy/gnosis-ica-strategy.yaml --dry-run`pull/4126/head
parent
80ac5d28e5
commit
bb470aec25
@ -0,0 +1,5 @@ |
||||
--- |
||||
'@hyperlane-xyz/cli': minor |
||||
--- |
||||
|
||||
Add 'submit' command to CLI. |
@ -0,0 +1,11 @@ |
||||
chain: avalanche |
||||
submitter: |
||||
type: gnosisSafe |
||||
chain: avalanche |
||||
safeAddress: '0x7fd32493Ca3A38cDf78A4cb74F32f6292f822aBe' |
||||
transforms: |
||||
- type: interchainAccount |
||||
chain: ethereum |
||||
config: |
||||
origin: avalanche |
||||
owner: '0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb' |
@ -0,0 +1,5 @@ |
||||
chain: avalanche |
||||
submitter: |
||||
type: gnosisSafe |
||||
chain: avalanche |
||||
safeAddress: '0x7fd32493Ca3A38cDf78A4cb74F32f6292f822aBe' |
@ -0,0 +1,4 @@ |
||||
chain: alfajores |
||||
submitter: |
||||
type: impersonatedAccount |
||||
userAddress: '0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb' |
@ -0,0 +1,3 @@ |
||||
chain: alfajores |
||||
submitter: |
||||
type: jsonRpc |
@ -0,0 +1,8 @@ |
||||
[ |
||||
{ |
||||
"data": "0x0e72cc06000000000000000000000000744ad987ee7c65d3b3333bfc3e6ecbf963eb872a", |
||||
"to": "0x9a4a3124F2a86bB5BE46267De85D31762b7a05Fd", |
||||
"from": "0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb", |
||||
"chainId": 44787 |
||||
} |
||||
] |
@ -0,0 +1,8 @@ |
||||
[ |
||||
{ |
||||
"data": "0x0e72cc06000000000000000000000000744ad987ee7c65d3b3333bfc3e6ecbf963eb872a", |
||||
"to": "0x9a4a3124F2a86bB5BE46267De85D31762b7a05Fd", |
||||
"from": "0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb", |
||||
"chainId": 43114 |
||||
} |
||||
] |
@ -0,0 +1,42 @@ |
||||
import { runSubmit } from '../config/submit.js'; |
||||
import { CommandModuleWithWriteContext } from '../context/types.js'; |
||||
import { logBlue, logGray } from '../logger.js'; |
||||
|
||||
import { |
||||
dryRunCommandOption, |
||||
outputFileCommandOption, |
||||
strategyCommandOption, |
||||
transactionsCommandOption, |
||||
} from './options.js'; |
||||
|
||||
/** |
||||
* Submit command |
||||
*/ |
||||
export const submitCommand: CommandModuleWithWriteContext<{ |
||||
transactions: string; |
||||
strategy: string; |
||||
'dry-run': string; |
||||
receipts: string; |
||||
}> = { |
||||
command: 'submit', |
||||
describe: 'Submit transactions', |
||||
builder: { |
||||
transactions: transactionsCommandOption, |
||||
strategy: strategyCommandOption, |
||||
'dry-run': dryRunCommandOption, |
||||
receipts: outputFileCommandOption('./generated/transactions/receipts.yaml'), |
||||
}, |
||||
handler: async ({ context, transactions, receipts }) => { |
||||
logGray(`Hyperlane Submit`); |
||||
logGray(`----------------`); |
||||
|
||||
await runSubmit({ |
||||
context, |
||||
transactionsFilepath: transactions, |
||||
receiptsFilepath: receipts, |
||||
}); |
||||
|
||||
logBlue(`✅ Submission complete`); |
||||
process.exit(0); |
||||
}, |
||||
}; |
@ -1,27 +1,11 @@ |
||||
import { z } from 'zod'; |
||||
|
||||
import type { |
||||
EV5GnosisSafeTxSubmitterProps, |
||||
EV5ImpersonatedAccountTxSubmitterProps, |
||||
EV5InterchainAccountTxTransformerProps, |
||||
MultiProvider, |
||||
TxSubmitterType, |
||||
TxTransformerType, |
||||
SubmissionStrategySchema, |
||||
} from '@hyperlane-xyz/sdk'; |
||||
|
||||
export interface SubmitterBuilderSettings { |
||||
submitterMetadata: SubmitterMetadata; |
||||
transformersMetadata: TransformerMetadata[]; |
||||
export type SubmitterBuilderSettings = { |
||||
submissionStrategy: z.infer<typeof SubmissionStrategySchema>; |
||||
multiProvider: MultiProvider; |
||||
} |
||||
export interface SubmitterMetadata { |
||||
type: TxSubmitterType; |
||||
props: SubmitterProps; |
||||
} |
||||
export interface TransformerMetadata { |
||||
type: TxTransformerType; |
||||
props: TransformerProps; |
||||
} |
||||
|
||||
type SubmitterProps = |
||||
| EV5ImpersonatedAccountTxSubmitterProps |
||||
| EV5GnosisSafeTxSubmitterProps; |
||||
type TransformerProps = EV5InterchainAccountTxTransformerProps; |
||||
}; |
||||
|
@ -1,9 +1,17 @@ |
||||
import { ethers } from 'ethers'; |
||||
import { z } from 'zod'; |
||||
|
||||
import { CallDataSchema, PopulatedTransactionSchema } from './schemas.js'; |
||||
import { |
||||
CallDataSchema, |
||||
PopulatedTransactionSchema, |
||||
PopulatedTransactionsSchema, |
||||
} from './schemas.js'; |
||||
|
||||
export type PopulatedTransaction = z.infer<typeof PopulatedTransactionSchema> & |
||||
ethers.PopulatedTransaction; |
||||
export type PopulatedTransactions = z.infer< |
||||
typeof PopulatedTransactionsSchema |
||||
> & |
||||
ethers.PopulatedTransaction[]; |
||||
|
||||
export type CallData = z.infer<typeof CallDataSchema>; |
||||
|
Loading…
Reference in new issue