@@ -2,7 +2,7 @@ import { Flags } from "@oclif/core";
22import { getBuildType , type GasEstimate } from "@layr-labs/ecloud-sdk" ;
33import { getEnvironmentInteractive , getPrivateKeyInteractive } from "./utils/prompts" ;
44import { getDefaultEnvironment } from "./utils/globalConfig" ;
5- import { parseGwei } from "viem" ;
5+ import { type Address , formatEther , parseGwei , type PublicClient } from "viem" ;
66
77export type CommonFlags = {
88 verbose : boolean ;
@@ -11,6 +11,7 @@ export type CommonFlags = {
1111 "rpc-url" ?: string ;
1212 "max-fee-per-gas" ?: string ;
1313 "max-priority-fee" ?: string ;
14+ nonce ?: string ;
1415} ;
1516
1617export const commonFlags = {
@@ -46,18 +47,29 @@ export const commonFlags = {
4647 description : "Override max priority fee per gas in gwei (e.g., 5)" ,
4748 env : "ECLOUD_MAX_PRIORITY_FEE" ,
4849 } ) ,
50+ nonce : Flags . string ( {
51+ required : false ,
52+ description : 'Override transaction nonce (integer or "latest" to replace a stuck transaction)' ,
53+ } ) ,
4954} ;
5055
5156/**
52- * Apply user-provided gas overrides to an estimated GasEstimate.
57+ * Apply user-provided gas and nonce overrides to an estimated GasEstimate.
5358 * If the user passed --max-fee-per-gas or --max-priority-fee, those values
5459 * replace the estimated ones and maxCostWei/maxCostEth are recalculated.
60+ * If --nonce is provided as a number, it sets the transaction nonce explicitly.
61+ * If --nonce is "latest", the first unconfirmed nonce is fetched (to replace a stuck tx).
5562 */
56- export function applyGasOverrides ( estimate : GasEstimate , flags : CommonFlags ) : GasEstimate {
63+ export async function applyTxOverrides (
64+ estimate : GasEstimate ,
65+ flags : CommonFlags ,
66+ opts ?: { publicClient : PublicClient ; address : Address } ,
67+ ) : Promise < GasEstimate > {
5768 const maxFeeStr = flags [ "max-fee-per-gas" ] ;
5869 const priorityFeeStr = flags [ "max-priority-fee" ] ;
70+ const nonceStr = flags . nonce ;
5971
60- if ( ! maxFeeStr && ! priorityFeeStr ) return estimate ;
72+ if ( ! maxFeeStr && ! priorityFeeStr && nonceStr == null ) return estimate ;
6173
6274 let { gasLimit, maxFeePerGas, maxPriorityFeePerGas } = estimate ;
6375
@@ -74,10 +86,29 @@ export function applyGasOverrides(estimate: GasEstimate, flags: CommonFlags): Ga
7486 }
7587
7688 const maxCostWei = gasLimit * maxFeePerGas ;
77- const eth = Number ( maxCostWei ) / 1e18 ;
89+ const eth = Number ( formatEther ( maxCostWei ) ) ;
7890 const maxCostEth = eth . toFixed ( 6 ) . replace ( / \. ? 0 + $ / , "" ) || "<0.000001" ;
7991
80- return { gasLimit, maxFeePerGas, maxPriorityFeePerGas, maxCostWei, maxCostEth } ;
92+ let nonce : number | undefined ;
93+ if ( nonceStr != null ) {
94+ if ( nonceStr === "latest" ) {
95+ if ( ! opts ?. publicClient || ! opts ?. address ) {
96+ throw new Error ( "--nonce latest requires a public client and address" ) ;
97+ }
98+ nonce = await opts . publicClient . getTransactionCount ( {
99+ address : opts . address ,
100+ blockTag : "latest" ,
101+ } ) ;
102+ } else {
103+ const parsed = Number ( nonceStr ) ;
104+ if ( ! Number . isInteger ( parsed ) || parsed < 0 ) {
105+ throw new Error ( `Invalid nonce: "${ nonceStr } ". Must be a non-negative integer or "latest".` ) ;
106+ }
107+ nonce = parsed ;
108+ }
109+ }
110+
111+ return { gasLimit, maxFeePerGas, maxPriorityFeePerGas, maxCostWei, maxCostEth, nonce } ;
81112}
82113
83114// Prompt for missing required values interactively
0 commit comments