From 154ed036966641661b3a7c353d055daaf72483b0 Mon Sep 17 00:00:00 2001 From: katspaugh Date: Sat, 25 Oct 2025 13:24:19 +0200 Subject: [PATCH 1/2] feat: add sequential operation prompts and unify UI styling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement seamless sequential operation flows: - account create → deploy - tx create → sign - tx sign → execute/push (with intelligent branching) UI improvements: - Remove picocolors from p.intro() calls for consistent styling - Unify Ink spinner appearance to match clack/prompts - Fix duplicate spinner/success messages - Remove picocolors from console.log statements for cleaner output - Fix MaxListenersExceededWarning by increasing limit to 20 Technical changes: - Show brief success messages before prompts (not after) - Only show full success screens if user declines next step - Smart next-step suggestions based on transaction signature status - All prompts use default 'true' to streamline common workflows 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package-lock.json | 1 - package.json | 1 - src/commands/account/create.ts | 62 ++++++++++++++++-------- src/commands/account/deploy.ts | 17 +++---- src/commands/config/chains.ts | 7 ++- src/commands/tx/create.ts | 67 +++++++++++++++++--------- src/commands/tx/pull.ts | 3 +- src/commands/tx/sign.ts | 75 ++++++++++++++++++++++++++--- src/commands/tx/status.ts | 3 +- src/commands/tx/sync.ts | 3 +- src/commands/wallet/import.ts | 3 +- src/commands/wallet/use.ts | 3 +- src/index.ts | 4 ++ src/services/transaction-builder.ts | 5 +- src/ui/components/Spinner.tsx | 8 +-- src/ui/messages.ts | 11 ++--- 16 files changed, 185 insertions(+), 88 deletions(-) diff --git a/package-lock.json b/package-lock.json index abc0995..d3ec87b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "conf": "^13.0.1", "ink": "^6.3.1", "ink-spinner": "^5.0.0", - "picocolors": "^1.1.1", "react": "^19.2.0", "viem": "^2.21.8", "zod": "^3.24.1" diff --git a/package.json b/package.json index f0ef9ec..3620e80 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,6 @@ "conf": "^13.0.1", "ink": "^6.3.1", "ink-spinner": "^5.0.0", - "picocolors": "^1.1.1", "react": "^19.2.0", "viem": "^2.21.8", "zod": "^3.24.1" diff --git a/src/commands/account/create.ts b/src/commands/account/create.ts index 72d7be6..6f1d1a5 100644 --- a/src/commands/account/create.ts +++ b/src/commands/account/create.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { type Address } from 'viem' import { getConfigStore } from '../../storage/config-store.js' import { getSafeStorage } from '../../storage/safe-store.js' @@ -7,12 +6,13 @@ import { getWalletStorage } from '../../storage/wallet-store.js' import { SafeService } from '../../services/safe-service.js' import { isValidAddress } from '../../utils/validation.js' import { checksumAddress, shortenAddress } from '../../utils/ethereum.js' +import { formatSafeAddress } from '../../utils/eip3770.js' import { logError } from '../../ui/messages.js' import { renderScreen } from '../../ui/render.js' import { AccountCreateSuccessScreen } from '../../ui/screens/index.js' export async function createSafe() { - p.intro(pc.bgCyan(pc.black(' Create Safe Account '))) + p.intro('Create Safe Account') const configStore = getConfigStore() const safeStorage = getSafeStorage() @@ -27,7 +27,7 @@ export async function createSafe() { } console.log('') - console.log(pc.dim(`Active wallet: ${activeWallet.name} (${activeWallet.address})`)) + console.log(`Active wallet: ${activeWallet.name} (${activeWallet.address})`) console.log('') // Select chain @@ -62,7 +62,7 @@ export async function createSafe() { if (includeActiveWallet) { owners.push(checksumAddress(activeWallet.address)) - console.log(pc.green(`✓ Added ${shortenAddress(activeWallet.address)}`)) + console.log(`✓ Added ${shortenAddress(activeWallet.address)}`) } // Add more owners @@ -102,7 +102,7 @@ export async function createSafe() { const checksummed = checksumAddress(ownerAddress as string) owners.push(checksummed) - console.log(pc.green(`✓ Added ${shortenAddress(checksummed)}`)) + console.log(`✓ Added ${shortenAddress(checksummed)}`) } if (owners.length === 0) { @@ -145,18 +145,16 @@ export async function createSafe() { // Summary console.log('') - console.log(pc.bold('📋 Safe Configuration Summary')) + console.log('Safe Configuration Summary') console.log('') - console.log(` ${pc.dim('Chain:')} ${chain.name} (${chain.chainId})`) - console.log(` ${pc.dim('Version:')} 1.4.1`) - console.log(` ${pc.dim('Owners:')} ${owners.length}`) + console.log(` Chain: ${chain.name} (${chain.chainId})`) + console.log(` Version: 1.4.1`) + console.log(` Owners: ${owners.length}`) owners.forEach((owner, i) => { const isActive = owner.toLowerCase() === activeWallet.address.toLowerCase() - console.log( - ` ${pc.dim(`${i + 1}.`)} ${shortenAddress(owner)}${isActive ? pc.green(' (you)') : ''}` - ) + console.log(` ${i + 1}. ${shortenAddress(owner)}${isActive ? ' (you)' : ''}`) }) - console.log(` ${pc.dim('Threshold:')} ${thresholdNum} / ${owners.length}`) + console.log(` Threshold: ${thresholdNum} / ${owners.length}`) console.log('') const spinner = p.spinner() @@ -203,7 +201,7 @@ export async function createSafe() { throw new Error(`Could not find available Safe address after ${maxAttempts} attempts`) } - spinner.stop('Safe created!') + spinner.stop() // Save to storage const safe = safeStorage.createSafe({ @@ -218,13 +216,37 @@ export async function createSafe() { }, }) - // Display success screen with Safe details and next steps - await renderScreen(AccountCreateSuccessScreen, { - name: safe.name, - address: safe.address as Address, - chainId: safe.chainId, - chainName: chain.name, + // Show brief success message + const allChains = configStore.getAllChains() + const eip3770 = formatSafeAddress(safe.address as Address, safe.chainId, allChains) + console.log('') + console.log('✓ Safe created successfully!') + console.log('') + console.log(` Name: ${safe.name}`) + console.log(` Address: ${eip3770}`) + console.log(` Chain: ${chain.name}`) + console.log(` Status: Not deployed`) + console.log('') + + // Offer to deploy the Safe + const shouldDeploy = await p.confirm({ + message: 'Would you like to deploy this Safe now?', + initialValue: true, }) + + if (!p.isCancel(shouldDeploy) && shouldDeploy) { + console.log('') + const { deploySafe } = await import('./deploy.js') + await deploySafe(eip3770) + } else { + // Show full success screen with next steps + await renderScreen(AccountCreateSuccessScreen, { + name: safe.name, + address: safe.address as Address, + chainId: safe.chainId, + chainName: chain.name, + }) + } } catch (error) { spinner.stop('Failed to create Safe') logError(error instanceof Error ? error.message : 'Unknown error') diff --git a/src/commands/account/deploy.ts b/src/commands/account/deploy.ts index 5149dc0..0dd1c7a 100644 --- a/src/commands/account/deploy.ts +++ b/src/commands/account/deploy.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { type Address } from 'viem' import { getConfigStore } from '../../storage/config-store.js' import { getSafeStorage } from '../../storage/safe-store.js' @@ -11,7 +10,7 @@ import { renderScreen } from '../../ui/render.js' import { AccountDeploySuccessScreen } from '../../ui/screens/index.js' export async function deploySafe(account?: string) { - p.intro(pc.bgCyan(pc.black(' Deploy Safe '))) + p.intro('Deploy Safe') const configStore = getConfigStore() const safeStorage = getSafeStorage() @@ -100,7 +99,7 @@ export async function deploySafe(account?: string) { } } catch { // If we can't verify, log warning but continue - console.log(pc.yellow('⚠ Warning: Could not verify on-chain deployment status')) + console.log('⚠ Warning: Could not verify on-chain deployment status') } // Get active wallet @@ -114,15 +113,15 @@ export async function deploySafe(account?: string) { const eip3770 = formatSafeAddress(safe.address as Address, safe.chainId, chains) console.log('') - console.log(pc.bold('Safe to Deploy:')) - console.log(` ${pc.dim('Name:')} ${safe.name}`) - console.log(` ${pc.dim('Address:')} ${pc.cyan(eip3770)}`) - console.log(` ${pc.dim('Chain:')} ${chain.name}`) + console.log('Safe to Deploy:') + console.log(` Name: ${safe.name}`) + console.log(` Address: ${eip3770}`) + console.log(` Chain: ${chain.name}`) console.log( - ` ${pc.dim('Owners:')} ${safe.predictedConfig.threshold} / ${safe.predictedConfig.owners.length}` + ` Owners: ${safe.predictedConfig.threshold} / ${safe.predictedConfig.owners.length}` ) console.log('') - console.log(pc.dim(`Deploying with wallet: ${activeWallet.name} (${activeWallet.address})`)) + console.log(`Deploying with wallet: ${activeWallet.name} (${activeWallet.address})`) console.log('') const confirm = await p.confirm({ diff --git a/src/commands/config/chains.ts b/src/commands/config/chains.ts index 194849b..f7548ce 100644 --- a/src/commands/config/chains.ts +++ b/src/commands/config/chains.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { getConfigStore } from '../../storage/config-store.js' import type { ChainConfig } from '../../types/config.js' import { isValidChainId, isValidUrl } from '../../utils/validation.js' @@ -12,7 +11,7 @@ import { } from '../../ui/screens/index.js' export async function addChain() { - p.intro(pc.bgCyan(pc.black(' Add Chain '))) + p.intro('Add Chain') const configStore = getConfigStore() @@ -138,7 +137,7 @@ export async function addChain() { } export async function listChains() { - p.intro(pc.bgCyan(pc.black(' Configured Chains '))) + p.intro('Configured Chains') const configStore = getConfigStore() const chains = Object.values(configStore.getAllChains()) @@ -149,7 +148,7 @@ export async function listChains() { } export async function removeChain() { - p.intro(pc.bgCyan(pc.black(' Remove Chain '))) + p.intro('Remove Chain') const configStore = getConfigStore() const chains = configStore.getAllChains() diff --git a/src/commands/tx/create.ts b/src/commands/tx/create.ts index 96079ca..6309eb9 100644 --- a/src/commands/tx/create.ts +++ b/src/commands/tx/create.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { isAddress, type Address } from 'viem' import { getConfigStore } from '../../storage/config-store.js' import { getSafeStorage } from '../../storage/safe-store.js' @@ -148,15 +147,15 @@ export async function createTransaction() { // If contract, try to fetch ABI and use transaction builder if (isContract) { console.log('') - console.log(pc.dim('Attempting to fetch contract ABI...')) + console.log() const config = configStore.getConfig() const etherscanApiKey = config.preferences?.etherscanApiKey // Inform user about ABI source based on API key availability if (!etherscanApiKey) { - console.log(pc.dim(' Using Sourcify for ABI (free, no API key required)')) - console.log(pc.dim(' Note: Proxy contract detection requires an Etherscan API key')) + console.log(' Using Sourcify for ABI (free, no API key required)') + console.log(' Note: Proxy contract detection requires an Etherscan API key') } const abiService = new ABIService(chain, etherscanApiKey) @@ -171,18 +170,18 @@ export async function createTransaction() { // Check if Etherscan detected this as a proxy if (implementationAddress) { - console.log(pc.cyan(`✓ Proxy detected! Implementation: ${implementationAddress}`)) + console.log(`✓ Proxy detected! Implementation: ${implementationAddress}`) if (contractName) { - console.log(pc.green(`✓ Proxy ABI found: ${pc.bold(contractName)}`)) + console.log(`✓ Proxy ABI found: ${contractName}`) } else { - console.log(pc.green('✓ Proxy ABI found!')) + console.log('✓ Proxy ABI found!') } } else { if (contractName) { - console.log(pc.green(`✓ Contract ABI found: ${pc.bold(contractName)}`)) + console.log(`✓ Contract ABI found: ${contractName}`) } else { - console.log(pc.green('✓ Contract ABI found!')) + console.log('✓ Contract ABI found!') } } @@ -195,9 +194,9 @@ export async function createTransaction() { // Use implementation name as the main contract name if (implInfo.name) { contractName = implInfo.name - console.log(pc.green(`✓ Implementation ABI found: ${pc.bold(implInfo.name)}`)) + console.log(`✓ Implementation ABI found: ${implInfo.name}`) } else { - console.log(pc.green('✓ Implementation ABI found!')) + console.log('✓ Implementation ABI found!') } // Merge ABIs (implementation functions + proxy functions) @@ -225,17 +224,17 @@ export async function createTransaction() { } abi = combinedAbi - console.log(pc.dim(` Combined: ${abi.length} items total`)) + console.log(` Combined: ${abi.length} items total`) } catch (error) { - console.log(pc.yellow('⚠ Could not fetch implementation ABI, using proxy ABI only')) - console.log(pc.dim(` Found ${abi.length} items in proxy ABI`)) + console.log('⚠ Could not fetch implementation ABI, using proxy ABI only') + console.log(` Found ${abi.length} items in proxy ABI`) } } else { - console.log(pc.dim(` Found ${abi.length} items in ABI`)) + console.log(` Found ${abi.length} items in ABI`) } } catch (error) { - console.log(pc.yellow('⚠ Could not fetch ABI')) - console.log(pc.dim(' Contract may not be verified. Falling back to manual input.')) + console.log('⚠ Could not fetch ABI') + console.log(' Contract may not be verified. Falling back to manual input.') } // If ABI found, offer transaction builder @@ -244,7 +243,7 @@ export async function createTransaction() { console.log('') if (functions.length > 0) { - console.log(pc.green(`✓ Found ${functions.length} writable function(s)`)) + console.log(`✓ Found ${functions.length} writable function(s)`) const useBuilder = await p.confirm({ message: 'Use transaction builder to interact with contract?', @@ -295,9 +294,9 @@ export async function createTransaction() { data = result.data } } else { - console.log(pc.yellow('⚠ No writable functions found in ABI')) - console.log(pc.dim(' Contract may only have view/pure functions')) - console.log(pc.dim(' Falling back to manual input')) + console.log('⚠ No writable functions found in ABI') + console.log(' Contract may only have view/pure functions') + console.log(' Falling back to manual input') } } } @@ -413,11 +412,31 @@ export async function createTransaction() { activeWallet.address as Address ) - createSpinner.stop('Transaction created') + createSpinner.stop() - await renderScreen(TransactionCreateSuccessScreen, { - safeTxHash: createdTx.safeTxHash, + // Show transaction hash + console.log('') + console.log('✓ Transaction created successfully!') + console.log('') + console.log(` Safe TX Hash: ${createdTx.safeTxHash}`) + console.log('') + + // Offer to sign the transaction + const shouldSign = await p.confirm({ + message: 'Would you like to sign this transaction now?', + initialValue: true, }) + + if (!p.isCancel(shouldSign) && shouldSign) { + console.log('') + const { signTransaction } = await import('./sign.js') + await signTransaction(createdTx.safeTxHash) + } else { + // Show full success screen with next steps + await renderScreen(TransactionCreateSuccessScreen, { + safeTxHash: createdTx.safeTxHash, + }) + } } catch (error) { if (error instanceof SafeCLIError) { p.log.error(error.message) diff --git a/src/commands/tx/pull.ts b/src/commands/tx/pull.ts index 0393685..55cc855 100644 --- a/src/commands/tx/pull.ts +++ b/src/commands/tx/pull.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import type { Address } from 'viem' import { getConfigStore } from '../../storage/config-store.js' import { getSafeStorage } from '../../storage/safe-store.js' @@ -12,7 +11,7 @@ import { renderScreen } from '../../ui/render.js' import { TransactionPullSuccessScreen, type TransactionPullResult } from '../../ui/screens/index.js' export async function pullTransactions(account?: string) { - p.intro(pc.bgCyan(pc.black(' Pull Transactions from Safe API '))) + p.intro('Pull Transactions from Safe API') try { const configStore = getConfigStore() diff --git a/src/commands/tx/sign.ts b/src/commands/tx/sign.ts index 63a8670..66109aa 100644 --- a/src/commands/tx/sign.ts +++ b/src/commands/tx/sign.ts @@ -190,16 +190,79 @@ export async function signTransaction(safeTxHash?: string) { transactionStore.updateStatus(selectedSafeTxHash, TransactionStatus.SIGNED) } - spinner2.stop('Transaction signed') + spinner2.stop() // Check if we have enough signatures const updatedTx = transactionStore.getTransaction(selectedSafeTxHash)! + const currentSignatures = updatedTx.signatures?.length || 0 - await renderScreen(TransactionSignSuccessScreen, { - safeTxHash: selectedSafeTxHash, - currentSignatures: updatedTx.signatures?.length || 0, - requiredSignatures: threshold, - }) + // Show brief success message + console.log('') + console.log(`✓ Signature added (${currentSignatures}/${threshold} required)`) + console.log('') + + // Offer next action based on signature status + if (currentSignatures >= threshold) { + // Transaction is ready to execute + console.log('✓ Transaction is ready to execute!') + console.log('') + + const nextAction = (await p.select({ + message: 'What would you like to do?', + options: [ + { value: 'execute', label: 'Execute transaction on-chain', hint: 'Recommended' }, + { + value: 'push', + label: 'Push to Safe Transaction Service', + hint: 'Share with other signers', + }, + { value: 'skip', label: 'Skip for now' }, + ], + initialValue: 'execute', + })) as string + + if (!p.isCancel(nextAction)) { + console.log('') + if (nextAction === 'execute') { + const { executeTransaction } = await import('./execute.js') + await executeTransaction(selectedSafeTxHash) + } else if (nextAction === 'push') { + const { pushTransaction } = await import('./push.js') + await pushTransaction(selectedSafeTxHash) + } else { + // Show full success screen with next steps + await renderScreen(TransactionSignSuccessScreen, { + safeTxHash: selectedSafeTxHash, + currentSignatures, + requiredSignatures: threshold, + }) + } + } else { + p.outro('Done!') + } + } else { + // Need more signatures + console.log(`Still need ${threshold - currentSignatures} more signature(s)`) + console.log('') + + const shouldPush = await p.confirm({ + message: 'Would you like to push this transaction to Safe Transaction Service?', + initialValue: true, + }) + + if (!p.isCancel(shouldPush) && shouldPush) { + console.log('') + const { pushTransaction } = await import('./push.js') + await pushTransaction(selectedSafeTxHash) + } else { + // Show full success screen with next steps + await renderScreen(TransactionSignSuccessScreen, { + safeTxHash: selectedSafeTxHash, + currentSignatures, + requiredSignatures: threshold, + }) + } + } } catch (error) { if (error instanceof SafeCLIError) { p.log.error(error.message) diff --git a/src/commands/tx/status.ts b/src/commands/tx/status.ts index b41dfba..cc1b15b 100644 --- a/src/commands/tx/status.ts +++ b/src/commands/tx/status.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import type { Address } from 'viem' import { getConfigStore } from '../../storage/config-store.js' import { getSafeStorage } from '../../storage/safe-store.js' @@ -11,7 +10,7 @@ import { renderScreen } from '../../ui/render.js' import { TransactionStatusScreen } from '../../ui/screens/index.js' export async function showTransactionStatus(safeTxHash?: string) { - p.intro(pc.bgCyan(pc.black(' Transaction Status '))) + p.intro('Transaction Status') try { const configStore = getConfigStore() diff --git a/src/commands/tx/sync.ts b/src/commands/tx/sync.ts index f447693..be2eefc 100644 --- a/src/commands/tx/sync.ts +++ b/src/commands/tx/sync.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import type { Address } from 'viem' import { getConfigStore } from '../../storage/config-store.js' import { getSafeStorage } from '../../storage/safe-store.js' @@ -13,7 +12,7 @@ import { renderScreen } from '../../ui/render.js' import { TransactionSyncSuccessScreen } from '../../ui/screens/index.js' export async function syncTransactions(account?: string) { - p.intro(pc.bgCyan(pc.black(' Sync Transactions with Safe API '))) + p.intro('Sync Transactions with Safe API') try { const configStore = getConfigStore() diff --git a/src/commands/wallet/import.ts b/src/commands/wallet/import.ts index 91a7158..7dcf7b7 100644 --- a/src/commands/wallet/import.ts +++ b/src/commands/wallet/import.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { type Address } from 'viem' import { getWalletStorage } from '../../storage/wallet-store.js' import { isValidPrivateKey } from '../../utils/validation.js' @@ -8,7 +7,7 @@ import { renderScreen } from '../../ui/render.js' import { WalletImportSuccessScreen } from '../../ui/screens/index.js' export async function importWallet() { - p.intro(pc.bgCyan(pc.black(' Import Wallet '))) + p.intro('Import Wallet') const walletStorage = getWalletStorage() diff --git a/src/commands/wallet/use.ts b/src/commands/wallet/use.ts index b253340..b2ffd49 100644 --- a/src/commands/wallet/use.ts +++ b/src/commands/wallet/use.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { type Address } from 'viem' import { getWalletStorage } from '../../storage/wallet-store.js' import { shortenAddress } from '../../utils/ethereum.js' @@ -8,7 +7,7 @@ import { renderScreen } from '../../ui/render.js' import { WalletUseSuccessScreen } from '../../ui/screens/index.js' export async function useWallet() { - p.intro(pc.bgCyan(pc.black(' Switch Wallet '))) + p.intro('Switch Wallet') const walletStorage = getWalletStorage() const wallets = walletStorage.getAllWallets() diff --git a/src/index.ts b/src/index.ts index fbddfb7..7ff3caf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,7 @@ import { program } from './cli.js' +// Increase max listeners to accommodate sequential command chaining +// (create → sign → execute, etc.) +process.setMaxListeners(20) + program.parse(process.argv) diff --git a/src/services/transaction-builder.ts b/src/services/transaction-builder.ts index 8edd556..03888e2 100644 --- a/src/services/transaction-builder.ts +++ b/src/services/transaction-builder.ts @@ -1,5 +1,4 @@ import * as p from '@clack/prompts' -import pc from 'picocolors' import { encodeFunctionData, parseEther, type Address } from 'viem' import type { ABIFunction, ABI } from './abi-service.js' import { SafeCLIError } from '../utils/errors.js' @@ -54,7 +53,7 @@ export class TransactionBuilder { // Prompt for each parameter if (func.inputs.length > 0) { console.log('') - console.log(pc.bold('Function Parameters:')) + console.log('Function Parameters:') console.log('') for (const input of func.inputs) { @@ -84,7 +83,7 @@ export class TransactionBuilder { */ private async promptForParameter(name: string, type: string): Promise { const value = await p.text({ - message: `${name} (${pc.cyan(type)}):`, + message: `${name} (${type}):`, placeholder: this.getPlaceholder(type), validate: (val) => { if (!val) return 'Value is required' diff --git a/src/ui/components/Spinner.tsx b/src/ui/components/Spinner.tsx index 634302e..a843f6e 100644 --- a/src/ui/components/Spinner.tsx +++ b/src/ui/components/Spinner.tsx @@ -17,23 +17,23 @@ export interface SpinnerProps { /** * Spinner component for displaying loading states. - * Replaces p.spinner() from @clack/prompts with Ink-native spinner. + * Styled to match @clack/prompts visual style for consistency. * * @example * ```tsx * - * + * * ``` */ export function Spinner({ message, type = 'dots' }: SpinnerProps): React.ReactElement { return ( - + {message && ( - {message} + {message} )} diff --git a/src/ui/messages.ts b/src/ui/messages.ts index 5ffd431..e5e771e 100644 --- a/src/ui/messages.ts +++ b/src/ui/messages.ts @@ -1,22 +1,21 @@ -import pc from 'picocolors' import * as p from '@clack/prompts' export function logSuccess(message: string): void { - p.log.success(pc.green(message)) + p.log.success(message) } export function logError(message: string): void { - p.log.error(pc.red(message)) + p.log.error(message) } export function logWarning(message: string): void { - p.log.warning(pc.yellow(message)) + p.log.warning(message) } export function logInfo(message: string): void { - p.log.info(pc.blue(message)) + p.log.info(message) } export function logStep(message: string): void { - p.log.step(pc.cyan(message)) + p.log.step(message) } From a4976f1cd1eb3c739ade19660f2ed8a0b13d203f Mon Sep 17 00:00:00 2001 From: katspaugh Date: Sun, 26 Oct 2025 07:51:14 +0100 Subject: [PATCH 2/2] fix: restore missing console.log message for ABI fetching --- src/commands/tx/create.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/tx/create.ts b/src/commands/tx/create.ts index 6309eb9..6cd4212 100644 --- a/src/commands/tx/create.ts +++ b/src/commands/tx/create.ts @@ -147,7 +147,7 @@ export async function createTransaction() { // If contract, try to fetch ABI and use transaction builder if (isContract) { console.log('') - console.log() + console.log('Attempting to fetch contract ABI...') const config = configStore.getConfig() const etherscanApiKey = config.preferences?.etherscanApiKey