@@ -10,7 +10,11 @@ import {
1010 ensureChainConfigured ,
1111 checkCancelled ,
1212 handleCommandError ,
13+ isNonInteractiveMode ,
14+ outputSuccess ,
15+ outputError ,
1316} from '../../utils/command-helpers.js'
17+ import { ExitCode } from '../../constants/exit-codes.js'
1418import {
1519 selectDeployedSafe ,
1620 fetchSafeOwnersAndThreshold ,
@@ -34,7 +38,9 @@ export async function addOwner(
3438 ownerAddress ?: string ,
3539 options : AddOwnerOptions = { }
3640) {
37- p . intro ( pc . bgCyan ( pc . black ( ' Add Safe Owner ' ) ) )
41+ if ( ! isNonInteractiveMode ( ) ) {
42+ p . intro ( pc . bgCyan ( pc . black ( ' Add Safe Owner ' ) ) )
43+ }
3844
3945 try {
4046 const ctx = createCommandContext ( )
@@ -62,15 +68,11 @@ export async function addOwner(
6268
6369 const safe = ctx . safeStorage . getSafe ( chainId , address )
6470 if ( ! safe ) {
65- p . log . error ( `Safe not found: ${ address } on chain ${ chainId } ` )
66- p . cancel ( 'Operation cancelled' )
67- return
71+ outputError ( `Safe not found: ${ address } on chain ${ chainId } ` , ExitCode . SAFE_NOT_FOUND )
6872 }
6973
7074 if ( ! safe . deployed ) {
71- p . log . error ( 'Safe must be deployed before adding owners' )
72- p . cancel ( 'Operation cancelled' )
73- return
75+ outputError ( 'Safe must be deployed before adding owners' , ExitCode . ERROR )
7476 }
7577
7678 // Get chain
@@ -100,16 +102,18 @@ export async function addOwner(
100102
101103 // Check for duplicates
102104 if ( isAddressAlreadyOwner ( newOwner , currentOwners ) ) {
103- p . log . error ( 'Address is already an owner' )
104- p . outro ( 'Failed' )
105- return
105+ outputError ( 'Address is already an owner' , ExitCode . INVALID_ARGS )
106106 }
107107 } catch ( error ) {
108- p . log . error ( error instanceof Error ? error . message : 'Invalid address' )
109- p . outro ( 'Failed' )
110- return
108+ outputError (
109+ error instanceof Error ? error . message : 'Invalid address' ,
110+ ExitCode . INVALID_ARGS
111+ )
111112 }
112113 } else {
114+ if ( isNonInteractiveMode ( ) ) {
115+ outputError ( 'Owner address is required in non-interactive mode' , ExitCode . INVALID_ARGS )
116+ }
113117 // Prompt for new owner address
114118 const newOwnerInput = await p . text ( {
115119 message : 'New owner address (supports EIP-3770 format: shortName:address):' ,
@@ -149,9 +153,10 @@ export async function addOwner(
149153 'Owner address'
150154 )
151155 } catch ( error ) {
152- p . log . error ( error instanceof Error ? error . message : 'Invalid address' )
153- p . outro ( 'Failed' )
154- return
156+ outputError (
157+ error instanceof Error ? error . message : 'Invalid address' ,
158+ ExitCode . INVALID_ARGS
159+ )
155160 }
156161 }
157162
@@ -162,14 +167,13 @@ export async function addOwner(
162167 // Use provided threshold
163168 const num = parseInt ( options . threshold , 10 )
164169 if ( isNaN ( num ) || num < 1 ) {
165- p . log . error ( 'Threshold must be at least 1' )
166- p . outro ( 'Failed' )
167- return
170+ outputError ( 'Threshold must be at least 1' , ExitCode . INVALID_ARGS )
168171 }
169172 if ( num > currentOwners . length + 1 ) {
170- p . log . error ( `Threshold cannot exceed ${ currentOwners . length + 1 } owners` )
171- p . outro ( 'Failed' )
172- return
173+ outputError (
174+ `Threshold cannot exceed ${ currentOwners . length + 1 } owners` ,
175+ ExitCode . INVALID_ARGS
176+ )
173177 }
174178 thresholdNum = num
175179 } else {
@@ -194,29 +198,31 @@ export async function addOwner(
194198 thresholdNum = parseInt ( newThreshold as string , 10 )
195199 }
196200
197- // Show summary
198- console . log ( '' )
199- console . log ( pc . bold ( 'Add Owner Summary:' ) )
200- console . log ( ` ${ pc . dim ( 'Safe:' ) } ${ safe . name } ` )
201- console . log ( ` ${ pc . dim ( 'New Owner:' ) } ${ newOwner } ` )
202- console . log ( ` ${ pc . dim ( 'Current Owners:' ) } ${ currentOwners . length } ` )
203- console . log ( ` ${ pc . dim ( 'New Owners:' ) } ${ currentOwners . length + 1 } ` )
204- console . log ( ` ${ pc . dim ( 'Old Threshold:' ) } ${ currentThreshold } ` )
205- console . log ( ` ${ pc . dim ( 'New Threshold:' ) } ${ thresholdNum } ` )
206- console . log ( '' )
207-
208- const confirm = await p . confirm ( {
209- message : 'Create transaction to add this owner?' ,
210- initialValue : true ,
211- } )
212-
213- if ( ! checkCancelled ( confirm ) || ! confirm ) {
214- p . cancel ( 'Operation cancelled' )
215- return
201+ if ( ! isNonInteractiveMode ( ) ) {
202+ // Show summary
203+ console . log ( '' )
204+ console . log ( pc . bold ( 'Add Owner Summary:' ) )
205+ console . log ( ` ${ pc . dim ( 'Safe:' ) } ${ safe . name } ` )
206+ console . log ( ` ${ pc . dim ( 'New Owner:' ) } ${ newOwner } ` )
207+ console . log ( ` ${ pc . dim ( 'Current Owners:' ) } ${ currentOwners . length } ` )
208+ console . log ( ` ${ pc . dim ( 'New Owners:' ) } ${ currentOwners . length + 1 } ` )
209+ console . log ( ` ${ pc . dim ( 'Old Threshold:' ) } ${ currentThreshold } ` )
210+ console . log ( ` ${ pc . dim ( 'New Threshold:' ) } ${ thresholdNum } ` )
211+ console . log ( '' )
212+
213+ const confirm = await p . confirm ( {
214+ message : 'Create transaction to add this owner?' ,
215+ initialValue : true ,
216+ } )
217+
218+ if ( ! checkCancelled ( confirm ) || ! confirm ) {
219+ p . cancel ( 'Operation cancelled' )
220+ return
221+ }
216222 }
217223
218- const spinner = p . spinner ( )
219- spinner . start ( 'Creating add owner transaction...' )
224+ const spinner = ! isNonInteractiveMode ( ) ? p . spinner ( ) : null
225+ spinner ? .start ( 'Creating add owner transaction...' )
220226
221227 // The addOwnerWithThreshold method encodes the transaction data
222228 const txService = new TransactionService ( chain )
@@ -235,14 +241,26 @@ export async function addOwner(
235241 activeWallet . address as Address
236242 )
237243
238- spinner . stop ( 'Transaction created' )
244+ spinner ? .stop ( 'Transaction created' )
239245
240- await renderScreen ( OwnerAddSuccessScreen , {
241- safeTxHash : safeTransaction . safeTxHash ,
242- safeAddress : safe . address as Address ,
243- chainId : safe . chainId ,
244- threshold : currentThreshold ,
245- } )
246+ if ( isNonInteractiveMode ( ) ) {
247+ outputSuccess ( 'Add owner transaction created' , {
248+ safeTxHash : safeTransaction . safeTxHash ,
249+ safeAddress : safe . address ,
250+ chainId : safe . chainId ,
251+ chainName : chain . name ,
252+ newOwner,
253+ newThreshold : thresholdNum ,
254+ totalOwners : currentOwners . length + 1 ,
255+ } )
256+ } else {
257+ await renderScreen ( OwnerAddSuccessScreen , {
258+ safeTxHash : safeTransaction . safeTxHash ,
259+ safeAddress : safe . address as Address ,
260+ chainId : safe . chainId ,
261+ threshold : currentThreshold ,
262+ } )
263+ }
246264 } catch ( error ) {
247265 handleCommandError ( error )
248266 }
0 commit comments