diff --git a/abi/MiniMeToken.json b/abi/MiniMeToken.json new file mode 100644 index 0000000..106b9f4 --- /dev/null +++ b/abi/MiniMeToken.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"creationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newController","type":"address"}],"name":"changeController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_blockNumber","type":"uint256"}],"name":"balanceOfAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_cloneTokenName","type":"string"},{"name":"_cloneDecimalUnits","type":"uint8"},{"name":"_cloneTokenSymbol","type":"string"},{"name":"_snapshotBlock","type":"uint256"},{"name":"_transfersEnabled","type":"bool"}],"name":"createCloneToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"parentToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_amount","type":"uint256"}],"name":"generateTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"transfersEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"parentSnapShotBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_amount","type":"uint256"}],"name":"destroyTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"claimTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenFactory","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_transfersEnabled","type":"bool"}],"name":"enableTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_tokenFactory","type":"address"},{"name":"_parentToken","type":"address"},{"name":"_parentSnapShotBlock","type":"uint256"},{"name":"_tokenName","type":"string"},{"name":"_decimalUnits","type":"uint8"},{"name":"_tokenSymbol","type":"string"},{"name":"_transfersEnabled","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_token","type":"address"},{"indexed":true,"name":"_controller","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"ClaimedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_cloneToken","type":"address"},{"indexed":false,"name":"_snapshotBlock","type":"uint256"}],"name":"NewCloneToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Approval","type":"event"}] diff --git a/contracts/index.ts b/contracts/index.ts index 892e67f..58468d8 100644 --- a/contracts/index.ts +++ b/contracts/index.ts @@ -4,6 +4,7 @@ export * from './burner'; export * from './deposit-contract'; export * from './dsm'; export * from './ens'; +export * from './ldo'; export * from './lido'; export * from './locator'; export * from './nor'; diff --git a/contracts/ldo.ts b/contracts/ldo.ts new file mode 100644 index 0000000..b728439 --- /dev/null +++ b/contracts/ldo.ts @@ -0,0 +1,7 @@ +import { Contract } from 'ethers'; +import { wallet } from '@providers'; +import { getDeployedAddress } from '@configs'; +import abi from 'abi/MiniMeToken.json'; + +export const ldoAddress = getDeployedAddress('ldo'); +export const ldoContract = new Contract(ldoAddress, abi, wallet); diff --git a/programs/accounting-oracle.ts b/programs/accounting-oracle.ts index 3c53f36..196d29c 100644 --- a/programs/accounting-oracle.ts +++ b/programs/accounting-oracle.ts @@ -7,6 +7,7 @@ import { addOssifiableProxyCommands, addParsingCommands, } from './common'; +import { logger } from '@utils'; const oracle = program.command('accounting-oracle').description('interact with accounting oracle contract'); addAccessControlSubCommands(oracle, accountingOracleContract); @@ -20,7 +21,7 @@ oracle .description('returns extra data format') .action(async () => { const format = await accountingOracleContract.EXTRA_DATA_FORMAT_LIST(); - console.log('extra data format', format); + logger.log('Extra data format', format); }); oracle @@ -28,7 +29,7 @@ oracle .description('returns extra type for stuck validators') .action(async () => { const format = await accountingOracleContract.EXTRA_DATA_TYPE_STUCK_VALIDATORS(); - console.log('type stuck', format); + logger.log('Type stuck', format); }); oracle @@ -36,5 +37,5 @@ oracle .description('returns extra type for exited validators') .action(async () => { const format = await accountingOracleContract.EXTRA_DATA_TYPE_EXITED_VALIDATORS(); - console.log('type exited', format); + logger.log('Type exited', format); }); diff --git a/programs/accounts.ts b/programs/accounts.ts index f58a7aa..67edf6b 100644 --- a/programs/accounts.ts +++ b/programs/accounts.ts @@ -2,7 +2,7 @@ import { program } from '@command'; import { wallet } from '@providers'; import { join } from 'path'; import { Wallet } from 'ethers'; -import { writeToFile } from '@utils'; +import { logger, writeToFile } from '@utils'; const accounts = program.command('accounts').description('accounts utils'); @@ -12,9 +12,9 @@ accounts .action(async () => { const wallet = Wallet.createRandom(); - console.table({ - address: wallet.address, - 'private key': wallet.privateKey, + logger.table({ + Address: wallet.address, + 'Private key': wallet.privateKey, }); }); @@ -22,7 +22,7 @@ accounts .command('address') .description('returns address from private key') .action(async () => { - console.log(wallet.address); + logger.log('Address', wallet.address); }); accounts diff --git a/programs/common/access-control.ts b/programs/common/access-control.ts index 89692b7..eeaf31a 100644 --- a/programs/common/access-control.ts +++ b/programs/common/access-control.ts @@ -1,6 +1,6 @@ import { Command } from 'commander'; import { Contract } from 'ethers'; -import { authorizedCall, getRoleHash } from '@utils'; +import { authorizedCall, getRoleHash, logger } from '@utils'; import { wallet } from '@providers'; export const addAccessControlSubCommands = (command: Command, contract: Contract) => { @@ -10,7 +10,7 @@ export const addAccessControlSubCommands = (command: Command, contract: Contract .argument('', 'role name') .action(async (role) => { const roleHash = await getRoleHash(contract, role); - console.log('role hash', roleHash); + logger.log('Role hash', roleHash); }); command @@ -20,7 +20,7 @@ export const addAccessControlSubCommands = (command: Command, contract: Contract .action(async (role) => { const roleHash = await getRoleHash(contract, role); const roleAdmin = await contract.getRoleAdmin(roleHash); - console.log('role admin', roleAdmin); + logger.log('Role admin', roleAdmin); }); command @@ -33,7 +33,7 @@ export const addAccessControlSubCommands = (command: Command, contract: Contract for (let i = 0; i < count; i++) { const count = await contract.getRoleMember(roleHash, i); - console.log(`role member at ${i}`, count); + logger.log(`Role member at ${i}`, count); } }); @@ -46,7 +46,7 @@ export const addAccessControlSubCommands = (command: Command, contract: Contract const { address } = options; const roleHash = await getRoleHash(contract, role); const result = await contract.hasRole(roleHash, address); - console.log('can perform', result); + logger.log('Can perform', result); }); command diff --git a/programs/common/aragon-app.ts b/programs/common/aragon-app.ts index 652a542..4333b27 100644 --- a/programs/common/aragon-app.ts +++ b/programs/common/aragon-app.ts @@ -9,7 +9,7 @@ import { getPublicResolverContract, getRepoContract, } from '@contracts'; -import { authorizedCall, forwardVoteFromTm, getRoleHash } from '@utils'; +import { authorizedCall, forwardVoteFromTm, getRoleHash, logger } from '@utils'; import { wallet } from '@providers'; import { updateAragonApp, votingForward } from '@scripts'; @@ -23,7 +23,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => .argument('', 'role name') .action(async (role) => { const roleHash = await getRoleHash(contract, role); - console.log('role hash', roleHash); + logger.log('Role hash', roleHash); }); command @@ -35,7 +35,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => const { address } = options; const roleHash = await getRoleHash(contract, role); const result = await contract.canPerform(address, roleHash, []); - console.log('can perform', result); + logger.log('Can perform', result); }); command @@ -49,7 +49,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => const appAddress = await contract.getAddress(); const result = await kernelContract.hasPermission(address, appAddress, roleHash, '0x'); - console.log('has permission', result); + logger.log('Has permission', result); }); command @@ -63,7 +63,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => const appAddress = await contract.getAddress(); const result = await aclContract.hasPermission(address, appAddress, roleHash); - console.log('has permission', result); + logger.log('Has permission', result); }); command @@ -75,7 +75,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => const appAddress = await contract.getAddress(); const manager = await aclContract.getPermissionManager(appAddress, roleHash); - console.log('manager', manager); + logger.log('Manager', manager); }); command @@ -123,7 +123,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => .description('returns proxy implementation address') .action(async () => { const implementation = await proxyContract.implementation(); - console.log('implementation', implementation); + logger.log('Implementation', implementation); }); command @@ -139,7 +139,7 @@ export const addAragonAppSubCommands = (command: Command, contract: Contract) => const repoContract = getRepoContract(getRepoAddress); const version = await repoContract.getLatest(); - console.log('version', version.toObject()); + logger.log('Version', version.toObject()); }); command diff --git a/programs/common/base-oracle.ts b/programs/common/base-oracle.ts index 8b9b6b3..72fdc04 100644 --- a/programs/common/base-oracle.ts +++ b/programs/common/base-oracle.ts @@ -1,4 +1,4 @@ -import { authorizedCall } from '@utils'; +import { authorizedCall, logger } from '@utils'; import { Command } from 'commander'; import { Contract } from 'ethers'; @@ -8,7 +8,7 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { .description('returns genesis time') .action(async () => { const genesisTime = await contract.GENESIS_TIME(); - console.log('genesis time', genesisTime); + logger.log('Genesis time', genesisTime); }); command @@ -21,7 +21,7 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { command.command('processing-state').action(async () => { const result = await contract.getProcessingState(); - console.log('result', result.toObject()); + logger.log('Result', result.toObject()); }); command @@ -29,7 +29,7 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { .description('returns seconds per slot') .action(async () => { const secondsPerSlot = await contract.SECONDS_PER_SLOT(); - console.log('seconds per slots', secondsPerSlot); + logger.log('Seconds per slots', secondsPerSlot); }); command @@ -37,7 +37,7 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { .description('returns consensus version') .action(async () => { const version = await contract.getConsensusVersion(); - console.log('version', version); + logger.log('Version', version); }); command @@ -53,7 +53,7 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { .description('returns consensus contract') .action(async () => { const consensusContract = await contract.getConsensusContract(); - console.log('consensus contract', consensusContract); + logger.log('Consensus contract', consensusContract); }); command @@ -61,7 +61,7 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { .description('returns consensus report') .action(async () => { const consensusReport = await contract.getConsensusReport(); - console.log('consensus report', consensusReport); + logger.log('Consensus report', consensusReport); }); command @@ -69,6 +69,6 @@ export const addBaseOracleCommands = (command: Command, contract: Contract) => { .description('returns last processing ref slot') .action(async () => { const refSlot = await contract.getLastProcessingRefSlot(); - console.log('last processing ref slot', refSlot); + logger.log('Last processing ref slot', refSlot); }); }; diff --git a/programs/common/consensus.ts b/programs/common/consensus.ts index a6ea627..ba67838 100644 --- a/programs/common/consensus.ts +++ b/programs/common/consensus.ts @@ -1,4 +1,4 @@ -import { authorizedCall, getLatestBlock, getProvider } from '@utils'; +import { authorizedCall, getLatestBlock, getProvider, logger } from '@utils'; import { Command } from 'commander'; import { Contract, EventLog, formatEther } from 'ethers'; @@ -24,7 +24,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { }), ); - console.table(table.sort((a, b) => b.lastReportedSlot - a.lastReportedSlot)); + logger.table(table.sort((a, b) => b.lastReportedSlot - a.lastReportedSlot)); }); command @@ -32,7 +32,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { .description('returns the quorum number') .action(async () => { const quorum = await contract.getQuorum(); - console.log('quorum', Number(quorum)); + logger.log('Quorum', Number(quorum)); }); command @@ -50,7 +50,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { .action(async (options) => { const { address } = options; const state = await contract.getConsensusStateForMember(address); - console.log('state', state.toObject()); + logger.log('State', state.toObject()); }); command @@ -78,7 +78,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { .description('returns the current frame') .action(async () => { const frame = await contract.getCurrentFrame(); - console.log('frame', frame.toObject()); + logger.log('Frame', frame.toObject()); }); command @@ -86,7 +86,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { .description('returns the chain config') .action(async () => { const config = await contract.getChainConfig(); - console.log('config', config.toObject()); + logger.log('Config', config.toObject()); }); command @@ -94,7 +94,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { .description('returns the frame config') .action(async () => { const config = await contract.getFrameConfig(); - console.log('config', config.toObject()); + logger.log('Config', config.toObject()); }); command @@ -121,7 +121,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { .argument('
', 'member address') .action(async (address) => { const state = await contract.getConsensusStateForMember(address); - console.log('member state', state); + logger.log('Member state', state); }); command @@ -195,8 +195,8 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { ]; }; - console.log('current slot'); - console.table([ + logger.log('Current slot'); + logger.table([ { value: 'current slot', slot: currentSlot, @@ -204,13 +204,13 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { }, ]); - console.log(); - console.log('current report frame'); - console.table(getFrameSlots(currentFrame)); + logger.log(); + logger.log('Current report frame'); + logger.table(getFrameSlots(currentFrame)); - console.log(); - console.log('next report frame'); - console.table(getFrameSlots(nextFrame)); + logger.log(); + logger.log('Next report frame'); + logger.table(getFrameSlots(nextFrame)); }); command @@ -241,7 +241,7 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { const groupedByRefSlot = events.reduce( (acc, event) => { if (!(event instanceof EventLog)) { - console.warn('log is not parsed'); + logger.warn('Log is not parsed'); return acc; } @@ -258,6 +258,6 @@ export const addConsensusCommands = (command: Command, contract: Contract) => { {} as Record>, ); - console.table(groupedByRefSlot); + logger.table(groupedByRefSlot); }); }; diff --git a/programs/common/erc20.ts b/programs/common/erc20.ts new file mode 100644 index 0000000..b8935c2 --- /dev/null +++ b/programs/common/erc20.ts @@ -0,0 +1,81 @@ +import { wallet } from '@providers'; +import { contractCallTxWithConfirm, logger } from '@utils'; +import { Command } from 'commander'; +import { Contract, MaxUint256, formatEther, parseEther } from 'ethers'; + +export const addERC20Commands = (command: Command, contract: Contract) => { + command + .command('name') + .description('returns token name') + .action(async () => { + const name = await contract.name(); + logger.log('Token name', name); + }); + + command + .command('symbol') + .description('returns token symbol') + .action(async () => { + const symbol = await contract.symbol(); + logger.log('Token symbol', symbol); + }); + + command + .command('decimals') + .description('returns token decimals') + .action(async () => { + const decimals = await contract.decimals(); + logger.log('Token decimals', decimals); + }); + + command + .command('total-supply') + .description('returns total supply') + .action(async () => { + const totalSupply = await contract.totalSupply(); + logger.log('Total supply', formatEther(totalSupply)); + }); + + command + .command('balance-of') + .argument('[address]', 'user address', wallet.address) + .action(async (address) => { + const balance = await contract.balanceOf(address); + logger.log('Balance', formatEther(balance)); + }); + + command + .command('transfer') + .argument('', 'to address') + .argument('', 'amount of tokens') + .action(async (to, amount) => { + await contractCallTxWithConfirm(contract, 'transfer', [to, parseEther(amount)]); + }); + + command + .command('transfer-from') + .argument('', 'from address') + .argument('', 'to address') + .argument('', 'amount of tokens') + .action(async (from, to, amount) => { + await contractCallTxWithConfirm(contract, 'transferFrom', [from, to, parseEther(amount)]); + }); + + command + .command('approve') + .argument('', 'spender address') + .argument('[amount]', 'amount of tokens') + .action(async (spender, amount) => { + const parsedAmount = amount ? parseEther(amount) : MaxUint256; + await contractCallTxWithConfirm(contract, 'approve', [spender, parsedAmount]); + }); + + command + .command('allowance') + .argument('', 'owner address') + .argument('', 'spender address') + .action(async (owner, spender) => { + const allowance = await contract.allowance(owner, spender); + logger.log('Allowance', formatEther(allowance)); + }); +}; diff --git a/programs/common/logs.ts b/programs/common/logs.ts index 2dd08f9..23802c5 100644 --- a/programs/common/logs.ts +++ b/programs/common/logs.ts @@ -1,4 +1,4 @@ -import { getLatestBlock, getProvider } from '@utils'; +import { getLatestBlock, getProvider, logger } from '@utils'; import { Command } from 'commander'; import { Contract, EventLog, Filter } from 'ethers'; @@ -44,6 +44,6 @@ export const addLogsCommands = (command: Command, contract: Contract) => { } }); - console.log(parsedLogs); + logger.dir(parsedLogs, { depth: null }); }); }; diff --git a/programs/common/parsing.ts b/programs/common/parsing.ts index 5526991..5e7cd61 100644 --- a/programs/common/parsing.ts +++ b/programs/common/parsing.ts @@ -1,3 +1,4 @@ +import { logger } from '@utils'; import { Command } from 'commander'; import { Contract, parseEther } from 'ethers'; @@ -11,11 +12,11 @@ export const addParsingCommands = (command: Command, contract: Contract) => { const { value } = options; const ethValue = parseEther(value); - console.log('tx value', ethValue); + logger.log('Tx value', ethValue); const tx = { data: calldata, value: ethValue }; const result = contract.interface.parseTransaction(tx); - console.log(result); + logger.log(result); }); command @@ -24,7 +25,7 @@ export const addParsingCommands = (command: Command, contract: Contract) => { .argument('', 'transaction revert reason') .action(async (errorData) => { const result = contract.interface.parseError(errorData); - console.log(result); + logger.log(result); }); command @@ -33,6 +34,6 @@ export const addParsingCommands = (command: Command, contract: Contract) => { .argument('', 'method hash') .action(async (method) => { const result = contract.interface.getFunction(method); - console.log(result); + logger.log(result); }); }; diff --git a/programs/common/pause-until.ts b/programs/common/pause-until.ts index 81acfb8..a30ff3f 100644 --- a/programs/common/pause-until.ts +++ b/programs/common/pause-until.ts @@ -1,4 +1,4 @@ -import { authorizedCall } from '@utils'; +import { authorizedCall, logger } from '@utils'; import { Command } from 'commander'; import { Contract, MaxUint256, toBeHex } from 'ethers'; @@ -8,7 +8,7 @@ export const addPauseUntilSubCommands = (command: Command, contract: Contract) = .description('returns is contract paused') .action(async () => { const paused = await contract.isPaused(); - console.log('paused', paused); + logger.log('Paused', paused); }); command diff --git a/programs/common/proxy.ts b/programs/common/proxy.ts index b68b2f2..7233564 100644 --- a/programs/common/proxy.ts +++ b/programs/common/proxy.ts @@ -1,7 +1,7 @@ import { Command } from 'commander'; import { Contract } from 'ethers'; import { getProxyContract } from '@contracts'; -import { authorizedCall } from '@utils'; +import { authorizedCall, logger } from '@utils'; export const addOssifiableProxyCommands = (command: Command, contract: Contract) => { const getProxyAddress = async () => await contract.getAddress(); @@ -12,7 +12,7 @@ export const addOssifiableProxyCommands = (command: Command, contract: Contract) .description('returns proxy implementation address') .action(async () => { const implementation = await proxyContract.proxy__getImplementation(); - console.log('implementation', implementation); + logger.log('Implementation', implementation); }); command @@ -20,7 +20,7 @@ export const addOssifiableProxyCommands = (command: Command, contract: Contract) .description('returns proxy admin address') .action(async () => { const admin = await proxyContract.proxy__getAdmin(); - console.log('admin', admin); + logger.log('Admin', admin); }); command diff --git a/programs/dsm.ts b/programs/dsm.ts index f7f3167..7bbb02e 100644 --- a/programs/dsm.ts +++ b/programs/dsm.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { dsmContract } from '@contracts'; -import { authorizedCall } from '@utils'; +import { authorizedCall, logger } from '@utils'; import { addLogsCommands, addParsingCommands } from './common'; const dsm = program.command('dsm').description('interact with deposit security module contract'); @@ -12,7 +12,7 @@ dsm .description('returns the owner of the contract') .action(async () => { const owner = await dsmContract.getOwner(); - console.log('owner', owner); + logger.log('Owner', owner); }); dsm @@ -28,7 +28,7 @@ dsm .description('returns the attest prefix for a message') .action(async () => { const prefix = await dsmContract.ATTEST_MESSAGE_PREFIX(); - console.log('prefix', prefix); + logger.log('Prefix', prefix); }); dsm @@ -36,7 +36,7 @@ dsm .description('returns the pause prefix for a message') .action(async () => { const prefix = await dsmContract.PAUSE_MESSAGE_PREFIX(); - console.log('prefix', prefix); + logger.log('Prefix', prefix); }); dsm @@ -44,7 +44,7 @@ dsm .description('returns the max amount of deposits per transaction') .action(async () => { const maxDeposits = await dsmContract.getMaxDeposits(); - console.log('max deposits', Number(maxDeposits)); + logger.log('Max deposits', Number(maxDeposits)); }); dsm @@ -60,7 +60,7 @@ dsm .description('returns the min deposits distance in blocks') .action(async () => { const minDistance = await dsmContract.getMinDepositBlockDistance(); - console.log('min distance', Number(minDistance)); + logger.log('Min distance', Number(minDistance)); }); dsm @@ -76,7 +76,7 @@ dsm .description('returns pause message validity period in blocks') .action(async () => { const period = await dsmContract.getPauseIntentValidityPeriodBlocks(); - console.log('period', Number(period)); + logger.log('Period', Number(period)); }); dsm @@ -92,7 +92,7 @@ dsm .description('returns the guardians quorum') .action(async () => { const quorum = await dsmContract.getGuardianQuorum(); - console.log('quorum', Number(quorum)); + logger.log('Quorum', Number(quorum)); }); dsm @@ -108,7 +108,7 @@ dsm .description('returns the list of guardians') .action(async () => { const guardians = await dsmContract.getGuardians(); - console.log('guardians', guardians); + logger.log('Guardians', guardians); }); dsm @@ -117,7 +117,7 @@ dsm .description('returns is deposits available') .action(async (moduleId) => { const canDeposit = await dsmContract.canDeposit(moduleId); - console.log('can deposit', canDeposit); + logger.log('Can deposit', canDeposit); }); dsm diff --git a/programs/exit-bus-oracle.ts b/programs/exit-bus-oracle.ts index f1188e2..96639d9 100644 --- a/programs/exit-bus-oracle.ts +++ b/programs/exit-bus-oracle.ts @@ -8,7 +8,7 @@ import { KAPIKey, ValidatorContainer, } from '@providers'; -import { exportToCSV, getValidatorsMap, groupByModuleId } from '@utils'; +import { exportToCSV, getValidatorsMap, groupByModuleId, logger } from '@utils'; import { addAccessControlSubCommands, @@ -51,8 +51,8 @@ oracle Object.entries(groupedRequests).forEach(([moduleId, requests]) => { const formattedRequests = formatExitRequests(requests); - console.log('module', moduleId); - console.table(formattedRequests); + logger.log('Module', moduleId); + logger.table(formattedRequests); }); }); @@ -69,13 +69,13 @@ oracle Object.entries(groupedRequests).forEach(([moduleId, requests]) => { const formattedRequests = formatExitRequestsDetailed(requests); - console.log('module', moduleId); + logger.log('Module', moduleId); if (agg) { const aggregatedRequestsByOperator = groupRequestsByOperator(formattedRequests); - console.table(aggregatedRequestsByOperator); + logger.table(aggregatedRequestsByOperator); } else { - console.table(formattedRequests); + logger.table(formattedRequests); } }); }); @@ -103,7 +103,7 @@ oracle .description('returns exit requests') .action(async () => { const value = await exitBusOracleContract.DATA_FORMAT_LIST(); - console.log('value', value); + logger.log('Value', value); }); oracle @@ -124,8 +124,8 @@ oracle return { operatorId, name, lastRequestedIndex }; }); - console.log('module', module.id, module.stakingModuleAddress); - console.table(operatorsWithLastRequestedValidators); + logger.log('Module', module.id, module.stakingModuleAddress); + logger.table(operatorsWithLastRequestedValidators); }); }); @@ -165,7 +165,7 @@ oracle const modules = await getStakingModules(); modules.forEach(async (module) => { - console.log('module', module.id, module.stakingModuleAddress); + logger.log('Module', module.id, module.stakingModuleAddress); const operators = await getNodeOperators(module.stakingModuleAddress); const operatorIds = operators.map(({ operatorId }) => operatorId); @@ -189,8 +189,8 @@ oracle const unsettled = unsettledRequests.length; if (unsettled > 0) { - console.log(`operator #${operatorId} ${name} has unsettled requests`); - console.table( + logger.log(`Operator #${operatorId} ${name} has unsettled requests`); + logger.table( unsettledRequests.map(({ validator }) => { const { validator: { pubkey }, @@ -200,7 +200,7 @@ oracle return { index, pubkey }; }), ); - console.log(''); + logger.log(''); } return { operatorId, name, lastRequestedIndex, exited, unsettled }; @@ -208,7 +208,7 @@ oracle const operatorsWithUnsettledRequests = detailedOperators.filter(({ unsettled }) => unsettled > 0); - console.log('summary'); - console.table(operatorsWithUnsettledRequests); + logger.log('Summary'); + logger.table(operatorsWithUnsettledRequests); }); }); diff --git a/programs/index.ts b/programs/index.ts index 8313dc5..fede942 100644 --- a/programs/index.ts +++ b/programs/index.ts @@ -6,6 +6,7 @@ export * from './deposit-contract'; export * from './dsm'; export * from './exit-bus-consensus'; export * from './exit-bus-oracle'; +export * from './ldo'; export * from './lido'; export * from './locator'; export * from './nor'; diff --git a/programs/ldo.ts b/programs/ldo.ts new file mode 100644 index 0000000..8181a86 --- /dev/null +++ b/programs/ldo.ts @@ -0,0 +1,10 @@ +import { program } from '@command'; +import { ldoContract } from '@contracts'; +import { addAragonAppSubCommands, addLogsCommands, addParsingCommands } from './common'; +import { addERC20Commands } from './common/erc20'; + +const ldo = program.command('ldo').description('interact with LDO contract'); +addAragonAppSubCommands(ldo, ldoContract); +addParsingCommands(ldo, ldoContract); +addLogsCommands(ldo, ldoContract); +addERC20Commands(ldo, ldoContract); diff --git a/programs/lido.ts b/programs/lido.ts index b5f8ef2..5b1b94a 100644 --- a/programs/lido.ts +++ b/programs/lido.ts @@ -1,15 +1,16 @@ -import { formatEther, MaxUint256, parseEther, ZeroAddress } from 'ethers'; +import { formatEther, parseEther, ZeroAddress } from 'ethers'; import { program } from '@command'; -import { wallet } from '@providers'; import { lidoContract } from '@contracts'; -import { authorizedCall, contractCallTxWithConfirm, forwardVoteFromTm } from '@utils'; +import { authorizedCall, contractCallTxWithConfirm, forwardVoteFromTm, logger } from '@utils'; import { resumeLidoAndSetStakingLimit, votingForward } from '@scripts'; import { addAragonAppSubCommands, addLogsCommands, addParsingCommands } from './common'; +import { addERC20Commands } from './common/erc20'; const lido = program.command('lido').description('interact with lido contract'); addAragonAppSubCommands(lido, lidoContract); addParsingCommands(lido, lidoContract); addLogsCommands(lido, lidoContract); +addERC20Commands(lido, lidoContract); lido .command('start-protocol') @@ -18,7 +19,7 @@ lido .action(async (options) => { const { stakingLimit } = options; const limit = parseEther(stakingLimit); - console.log('staking limit', limit); + logger.log('Staking limit', limit); const [lidoCalldata] = resumeLidoAndSetStakingLimit(limit); const [votingCalldata] = votingForward(lidoCalldata); @@ -26,20 +27,12 @@ lido await forwardVoteFromTm(votingCalldata); }); -lido - .command('total-supply') - .description('returns total stETH supply') - .action(async () => { - const totalSupply = await lidoContract.totalSupply(); - console.log('total supply', formatEther(totalSupply)); - }); - lido .command('total-shares') .description('returns total shares') .action(async () => { const totalShares = await lidoContract.getTotalShares(); - console.log('total shares', formatEther(totalShares)); + logger.log('Total shares', formatEther(totalShares)); }); lido @@ -47,7 +40,7 @@ lido .description('returns is protocol stopped') .action(async () => { const isStopped = await lidoContract.isStopped(); - console.log('is stopped', isStopped); + logger.log('Is stopped', isStopped); }); lido @@ -55,7 +48,7 @@ lido .description('returns is staking paused') .action(async () => { const isStakingPaused = await lidoContract.isStakingPaused(); - console.log('is staking paused', isStakingPaused); + logger.log('Is staking paused', isStakingPaused); }); lido @@ -63,7 +56,7 @@ lido .description('returns buffered ethers') .action(async () => { const bufferedEther = await lidoContract.getBufferedEther(); - console.log('buffered ether', formatEther(bufferedEther)); + logger.log('Buffered ether', formatEther(bufferedEther)); }); lido @@ -80,43 +73,7 @@ lido .description('returns depositable ether amount') .action(async () => { const amount = await lidoContract.getDepositableEther(); - console.log('depositable ether', formatEther(amount)); - }); - -lido - .command('approve') - .argument('', 'spender address') - .option('-a, --amount ', 'amount', '') - .action(async (spender, options) => { - const amount = options.amount ? parseEther(options.amount) : MaxUint256; - await contractCallTxWithConfirm(lidoContract, 'approve', [spender, amount]); - }); - -lido - .command('allowance') - .argument('', 'spender address') - .option('-o, --owner ', 'owner address', wallet.address) - .action(async (spender, options) => { - const { owner } = options; - const allowance = await lidoContract.allowance(owner, spender); - console.log('allowance', allowance); - }); - -lido - .command('balance') - .option('-a, --address ', 'user address', wallet.address) - .action(async (options) => { - const { address } = options; - const balance = await lidoContract.balanceOf(address); - console.log('balance', formatEther(balance)); - }); - -lido - .command('transfer') - .argument('', 'recipient address') - .argument('', 'amount of steth') - .action(async (recipient, amount) => { - await contractCallTxWithConfirm(lidoContract, 'transfer', [recipient, parseEther(amount)]); + logger.log('Depositable ether', formatEther(amount)); }); lido @@ -133,7 +90,7 @@ lido .description('returns staking limit') .action(async () => { const limit = await lidoContract.getStakeLimitFullInfo(); - console.log('staking limit', limit.toObject()); + logger.log('Staking limit', limit.toObject()); }); lido diff --git a/programs/locator.ts b/programs/locator.ts index df6a117..5eb6eef 100644 --- a/programs/locator.ts +++ b/programs/locator.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { getLocatorContract, locatorContract } from '@contracts'; -import { compareContractCalls } from '@utils'; +import { compareContractCalls, logger } from '@utils'; import { addOssifiableProxyCommands, addParsingCommands } from './common'; const locator = program.command('locator').description('interact with locator contract'); @@ -15,7 +15,7 @@ locator const [elRewardsVault, oracleReportSanityChecker, stakingRouter, treasury, withdrawalQueue, withdrawalVault] = components; - console.log('components', { + logger.log('Components', { elRewardsVault, oracleReportSanityChecker, stakingRouter, @@ -40,7 +40,7 @@ locator postTokenRebaseReceiver, ] = components; - console.log('components', { + logger.log('Components', { accountingOracle, elRewardsVault, oracleReportSanityChecker, @@ -83,7 +83,7 @@ locator locatorContract.oracleDaemonConfig(), ]); - console.log('components', { + logger.log('Components', { accountingOracle, elRewardsVault, oracleReportSanityChecker, @@ -106,7 +106,7 @@ locator .description('returns legacy oracle') .action(async () => { const address = await locatorContract.legacyOracle(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -114,7 +114,7 @@ locator .description('returns report sanity checker') .action(async () => { const address = await locatorContract.oracleReportSanityChecker(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -122,7 +122,7 @@ locator .description('returns accounting oracle') .action(async () => { const address = await locatorContract.accountingOracle(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -130,7 +130,7 @@ locator .description('returns exit bus oracle') .action(async () => { const address = await locatorContract.validatorsExitBusOracle(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -138,7 +138,7 @@ locator .description('returns deposit security module') .action(async () => { const address = await locatorContract.depositSecurityModule(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -146,7 +146,7 @@ locator .description('returns el rewards vault') .action(async () => { const address = await locatorContract.elRewardsVault(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -154,7 +154,7 @@ locator .description('returns lido') .action(async () => { const address = await locatorContract.lido(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -162,7 +162,7 @@ locator .description('returns post token rebase receiver') .action(async () => { const address = await locatorContract.postTokenRebaseReceiver(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -170,7 +170,7 @@ locator .description('returns burner') .action(async () => { const address = await locatorContract.burner(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -178,7 +178,7 @@ locator .description('returns staking router') .action(async () => { const address = await locatorContract.stakingRouter(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -186,7 +186,7 @@ locator .description('returns treasury') .action(async () => { const address = await locatorContract.treasury(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -194,7 +194,7 @@ locator .description('returns withdrawal queue') .action(async () => { const address = await locatorContract.withdrawalQueue(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -202,7 +202,7 @@ locator .description('returns withdrawal vault') .action(async () => { const address = await locatorContract.withdrawalVault(); - console.log('address', address); + logger.log('Address', address); }); locator @@ -210,7 +210,7 @@ locator .description('returns oracle config') .action(async () => { const address = await locatorContract.oracleDaemonConfig(); - console.log('address', address); + logger.log('Address', address); }); locator diff --git a/programs/nor.ts b/programs/nor.ts index e65ff38..0a12cce 100644 --- a/programs/nor.ts +++ b/programs/nor.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { norContract } from '@contracts'; -import { authorizedCall, contractCallTxWithConfirm, formatDate } from '@utils'; +import { authorizedCall, contractCallTxWithConfirm, formatDate, logger } from '@utils'; import { addAragonAppSubCommands, addLogsCommands, addParsingCommands } from './common'; import { getPenalizedOperators } from './staking-module'; @@ -14,7 +14,7 @@ nor .description('returns operators count') .action(async () => { const total = await norContract.getNodeOperatorsCount(); - console.log('total', total); + logger.log('Total', total); }); nor @@ -23,7 +23,7 @@ nor .argument('', 'operator id') .action(async (operatorId) => { const operator = await norContract.getNodeOperator(operatorId, true); - console.log('operator', operator.toObject()); + logger.log('Operator', operator.toObject()); }); nor @@ -32,7 +32,7 @@ nor .argument('', 'operator id') .action(async (operatorId) => { const summary = await norContract.getNodeOperatorSummary(operatorId); - console.log('operator summary', summary.toObject()); + logger.log('Operator summary', summary.toObject()); }); nor @@ -52,7 +52,7 @@ nor .argument('', 'key id') .action(async (operatorId, keyId) => { const keyData = await norContract.getSigningKey(Number(operatorId), Number(keyId)); - console.log('key', keyData); + logger.log('Key', keyData); }); nor @@ -95,7 +95,7 @@ nor const penalizedOperators = await getPenalizedOperators(); if (!penalizedOperators.length) { - console.log('no penalized operators'); + logger.log('No penalized operators'); return; } @@ -115,7 +115,7 @@ nor }; }); - console.table(formattedOperators); + logger.table(formattedOperators); }); nor @@ -133,22 +133,22 @@ nor const penalizedOperators = await getPenalizedOperators(); if (!penalizedOperators.length) { - console.log('no penalized operators'); + logger.log('No penalized operators'); return; } for (const operator of penalizedOperators) { - console.log('operator is penalized', operator.operatorId, operator.name); - console.log('current time', formatDate(new Date())); - console.log('penalty end time', formatDate(new Date(Number(operator.stuckPenaltyEndTimestamp) * 1000))); + logger.log('Operator is penalized', operator.operatorId, operator.name); + logger.log('Current time', formatDate(new Date())); + logger.log('Penalty end time', formatDate(new Date(Number(operator.stuckPenaltyEndTimestamp) * 1000))); if (operator.isPenaltyClearable) { - console.log('penalty can be cleared'); + logger.log('Penalty can be cleared'); await contractCallTxWithConfirm(norContract, 'clearNodeOperatorPenalty', [operator.operatorId]); } else { - console.log('penalty is not clearable'); + logger.log('Penalty is not clearable'); } } - console.log('all operators are checked'); + logger.log('All operators are checked'); }); diff --git a/programs/omnibus.ts b/programs/omnibus.ts index 085117c..a353b2a 100644 --- a/programs/omnibus.ts +++ b/programs/omnibus.ts @@ -1,6 +1,7 @@ import { program } from '@command'; -import { checkTmCanForward, forwardVoteFromTm } from '@utils'; +import { checkTmCanForward, forwardVoteFromTm, printTx } from '@utils'; import { printVoteTxData, promptVoting } from './omnibus/'; +import { tmContract } from '@contracts'; const omnibus = program.command('omnibus').description('preparing and launching batches of calls through voting'); @@ -12,6 +13,7 @@ omnibus if (!voteTxData) return; await printVoteTxData(voteTxData); + await printTx(tmContract, 'forward', [voteTxData.newVoteCalldata]); }); omnibus diff --git a/programs/omnibus/print-vote.ts b/programs/omnibus/print-vote.ts index 0f25c9c..1e0ae6a 100644 --- a/programs/omnibus/print-vote.ts +++ b/programs/omnibus/print-vote.ts @@ -1,23 +1,16 @@ -import { tmContract } from '@contracts'; -import { green } from 'chalk'; -import { printTx } from 'utils'; import { VoteTxData } from './prompt-voting'; +import { logger } from '@utils'; export const printVoteTxData = async (voteTxData: VoteTxData) => { const { voteEvmScript, newVoteCalldata, description } = voteTxData; - console.log(''); - console.log(green('vote calls evmScript:')); - console.log(voteEvmScript); + logger.success('\nVote calls evmScript:'); + logger.log(voteEvmScript); - console.log(''); - console.log(green('vote description (meta):')); - console.log(description); + logger.success('\nVote description (meta):'); + logger.log(description); - console.log(''); - console.log(green('newVote() calldata:')); - console.log(newVoteCalldata); + logger.success('\nnewVote() calldata:'); + logger.log(newVoteCalldata); - console.log(''); - - await printTx(tmContract, 'forward', [newVoteCalldata]); + logger.log(''); }; diff --git a/programs/omnibus/prompt-amount.ts b/programs/omnibus/prompt-amount.ts index fd40668..ffac4de 100644 --- a/programs/omnibus/prompt-amount.ts +++ b/programs/omnibus/prompt-amount.ts @@ -4,7 +4,7 @@ export const promptAmountOfCalls = async () => { const { amount } = await prompts({ type: 'number', name: 'amount', - message: 'enter amount of calls', + message: 'Enter amount of calls', }); return amount; diff --git a/programs/omnibus/prompt-call.ts b/programs/omnibus/prompt-call.ts index 4addbc4..c1933b1 100644 --- a/programs/omnibus/prompt-call.ts +++ b/programs/omnibus/prompt-call.ts @@ -1,28 +1,30 @@ -import { gray, bold, green } from 'chalk'; +import { logger } from '@utils'; +import chalk from 'chalk'; import prompts from 'prompts'; +const head = chalk.white.bold; +const title = chalk.gray; +const value = chalk.blue.bold; + export const printCallExample = () => { - console.log(''); - console.log(bold('enter calls one by one')); - console.log(`format: ${gray('address "method_signature(uint256,string)" arg1 arg2')}`); - console.log( - `example: ${gray( - `0x595F64Ddc3856a3b5Ff4f4CC1d1fb4B46cFd2bAC 'setNodeOperatorStakingLimit(uint256,uint64)' 0 150`, - )}`, + logger.log(head('\nEnter calls one by one')); + logger.log(title(` Format:`), value('address signature [...args]')); + logger.log( + title(`Example:`), + value(`0x595F64Ddc3856a3b5Ff4f4CC1d1fb4B46cFd2bAC 'setNodeOperatorStakingLimit(uint256,uint64)' 0 150`), ); - console.log(''); + logger.log(''); }; export const printCallsSuccess = () => { - console.log(green('filling the list of calls is completed')); - console.log(''); + logger.success('Filling the list of calls is completed\n'); }; export const promptMethodCall = async (index: number) => { const { methodCall } = await prompts({ type: 'text', name: 'methodCall', - message: `enter call ${index + 1}`, + message: `Enter call ${index + 1}`, }); return methodCall; diff --git a/programs/omnibus/prompt-description.ts b/programs/omnibus/prompt-description.ts index e366273..4971a14 100644 --- a/programs/omnibus/prompt-description.ts +++ b/programs/omnibus/prompt-description.ts @@ -11,7 +11,7 @@ export const getDefaultOmnibusDescription = (omnibusScripts: OmnibusScript[]) => .map(({ address, args, methodName }, index) => `${index + 1}) call ${methodName}(${args}) at ${address}`) .join('\n'); - return `omnibus: \n${callList}`; + return `Omnibus: \n${callList}`; }; export const promptOmnibusDescription = async (omnibusScripts: OmnibusScript[]) => { @@ -21,7 +21,7 @@ export const promptOmnibusDescription = async (omnibusScripts: OmnibusScript[]) type: 'text', name: 'description', initial: defaultDescription, - message: 'enter voting description (use \\n for new line): \n', + message: 'Enter voting description (use \\n for new line): \n', }); return (description ?? '').split('\\n').join('\n'); diff --git a/programs/omnibus/prompt-voting.ts b/programs/omnibus/prompt-voting.ts index 6e65651..713be19 100644 --- a/programs/omnibus/prompt-voting.ts +++ b/programs/omnibus/prompt-voting.ts @@ -1,4 +1,4 @@ -import { encodeCallScript, parseMethodCallToContract } from '@utils'; +import { encodeCallScript, logger, parseMethodCallToContract } from '@utils'; import { promptAmountOfCalls } from './prompt-amount'; import { printCallExample, printCallsSuccess, promptMethodCall } from './prompt-call'; import { OmnibusScript, promptOmnibusDescription } from './prompt-description'; @@ -27,11 +27,11 @@ export const promptVoting = async (): Promise => { const [encoded, call] = await agentOrDirect(contract, method, args); omnibusScripts.push({ encoded, call, ...parsedCall }); } catch (error) { - console.warn((error as Error).message); + logger.error(error); return; } } else { - console.warn('empty call, aborting'); + logger.warn('Empty call, aborting'); return; } } diff --git a/programs/oracle-config.ts b/programs/oracle-config.ts index 85587b4..4ab8801 100644 --- a/programs/oracle-config.ts +++ b/programs/oracle-config.ts @@ -2,6 +2,7 @@ import { Result, toBeHex, zeroPadValue } from 'ethers'; import { program } from '@command'; import { oracleConfigContract } from '@contracts'; import { addAccessControlSubCommands, addLogsCommands, addParsingCommands } from './common'; +import { logger } from '@utils'; const config = program.command('oracle-config').description('interact with oracle config contract'); addAccessControlSubCommands(config, oracleConfigContract); @@ -14,7 +15,7 @@ config .argument('', 'key') .action(async (key) => { const value = await oracleConfigContract.get(key); - console.log('value', value); + logger.log('Value', value); }); config @@ -25,7 +26,7 @@ config .action(async (key, value) => { const hexValue = zeroPadValue(toBeHex(Number(value)), 32); await oracleConfigContract.set(key, hexValue); - console.log('value set'); + logger.log('Value set'); }); config @@ -36,7 +37,7 @@ config .action(async (key, value) => { const hexValue = zeroPadValue(toBeHex(Number(value)), 32); await oracleConfigContract.update(key, hexValue); - console.log('value updated'); + logger.log('Value updated'); }); config @@ -45,7 +46,7 @@ config .argument('', 'key') .action(async (key) => { await oracleConfigContract.unset(key); - console.log('value unset'); + logger.log('Value unset'); }); config @@ -66,6 +67,6 @@ config const list: Result[] = await oracleConfigContract.getList(knownKeys); list.forEach((item, index) => { - console.log(knownKeys[index], Number(item)); + logger.log(knownKeys[index], Number(item)); }); }); diff --git a/programs/role.ts b/programs/role.ts index 49db300..80673ed 100644 --- a/programs/role.ts +++ b/programs/role.ts @@ -16,6 +16,7 @@ import { stakingRouterContract, withdrawalRequestContract, } from '@contracts'; +import { logger } from '@utils'; import { FunctionFragment } from 'ethers'; const role = program.command('role').description('roles utils'); @@ -51,7 +52,7 @@ role const roleHash = await contract[fragment.name](); if (roleHash !== hash) return; - console.log(fragment.name, roleHash); + logger.log(fragment.name, roleHash); } } catch { // diff --git a/programs/sanity-checker.ts b/programs/sanity-checker.ts index 17e0df1..eb28630 100644 --- a/programs/sanity-checker.ts +++ b/programs/sanity-checker.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { sanityCheckerContract } from '@contracts'; -import { authorizedCall } from '@utils'; +import { authorizedCall, logger } from '@utils'; import { addAccessControlSubCommands, addLogsCommands, addParsingCommands } from './common'; const sanityChecker = program.command('sanity-checker').description('interact with sanity checker contract'); @@ -13,7 +13,7 @@ sanityChecker .description('returns oracle report limits') .action(async () => { const limits = await sanityCheckerContract.getOracleReportLimits(); - console.log('limits', limits.toObject()); + logger.log('Limits', limits.toObject()); }); sanityChecker diff --git a/programs/scripts.ts b/programs/scripts.ts index e581ac3..99060b0 100644 --- a/programs/scripts.ts +++ b/programs/scripts.ts @@ -1,6 +1,7 @@ import { parseEther } from 'ethers'; import { program } from '@command'; import { resumeLidoAndSetStakingLimit, resumeProtocol, resumeStaking, setStakingLimit } from '@scripts'; +import { logger } from '@utils'; const scripts = program.command('scripts').description('aragon scripts builder'); @@ -9,7 +10,7 @@ scripts .description('returns encoded resume protocol script') .action(async () => { const [encoded] = resumeProtocol(); - console.log('encoded', encoded); + logger.log('Encoded', encoded); }); scripts @@ -17,7 +18,7 @@ scripts .description('returns encoded resume staking script') .action(async () => { const [encoded] = resumeStaking(); - console.log('encoded', encoded); + logger.log('Encoded', encoded); }); scripts @@ -29,7 +30,7 @@ scripts const limit = parseEther(stakingLimit); const [encoded] = setStakingLimit(limit); - console.log('encoded', encoded); + logger.log('Encoded', encoded); }); scripts @@ -41,5 +42,5 @@ scripts const limit = parseEther(stakingLimit); const [encoded] = resumeLidoAndSetStakingLimit(limit); - console.log('encoded', encoded); + logger.log('Encoded', encoded); }); diff --git a/programs/staking-router.ts b/programs/staking-router.ts index ee5250b..f8ab74d 100644 --- a/programs/staking-router.ts +++ b/programs/staking-router.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { stakingRouterContract } from '@contracts'; -import { authorizedCall } from '@utils'; +import { authorizedCall, logger } from '@utils'; import { Result } from 'ethers'; import { addAccessControlSubCommands, addLogsCommands, addOssifiableProxyCommands, addParsingCommands } from './common'; import { getNodeOperators, getStakingModules } from './staking-module'; @@ -16,7 +16,7 @@ router .description('returns staking modules') .action(async () => { const modules = await getStakingModules(); - console.log('modules', modules); + logger.log('Modules', modules); }); router @@ -25,7 +25,7 @@ router .argument('', 'staking module id') .action(async (moduleId) => { const module = await stakingRouterContract.getStakingModule(moduleId); - console.log('module', module); + logger.log('Module', module); }); router @@ -79,7 +79,7 @@ router .description('returns withdrawal credentials') .action(async () => { const withdrawalCredentials = await stakingRouterContract.getWithdrawalCredentials(); - console.log('withdrawal credentials', withdrawalCredentials); + logger.log('Withdrawal credentials', withdrawalCredentials); }); router @@ -88,7 +88,7 @@ router .argument('', 'module id') .action(async (moduleId) => { const isPaused = await stakingRouterContract.getStakingModuleIsDepositsPaused(moduleId); - console.log('module paused', isPaused); + logger.log('Module paused', isPaused); }); router @@ -97,7 +97,7 @@ router .argument('', 'module id') .action(async (moduleId) => { const block = await stakingRouterContract.getStakingModuleLastDepositBlock(moduleId); - console.log('last deposit block', block); + logger.log('Last deposit block', block); }); router @@ -106,7 +106,7 @@ router .argument('', 'module id') .action(async (moduleId) => { const block = await stakingRouterContract.getStakingModuleIsActive(moduleId); - console.log('is module active', block); + logger.log('Is module active', block); }); router @@ -115,7 +115,7 @@ router .argument('', 'module id') .action(async (moduleId) => { const nonce = await stakingRouterContract.getStakingModuleNonce(moduleId); - console.log('module nonce', nonce); + logger.log('Module nonce', nonce); }); router @@ -124,7 +124,7 @@ router .argument('', 'module id') .action(async (moduleId) => { const deposits = await stakingRouterContract.getStakingModuleMaxDepositsCount(moduleId); - console.log('max deposits', deposits); + logger.log('Max deposits', deposits); }); router @@ -133,7 +133,7 @@ router .argument('', 'deposits count') .action(async (depositsCount) => { const allocation = await stakingRouterContract.getDepositsAllocation(depositsCount); - console.log('allocation', allocation); + logger.log('Allocation', allocation); }); router @@ -176,8 +176,8 @@ router }; }); - console.log('module', module.id, module.stakingModuleAddress); - console.table(operatorsDigests); + logger.log('Module', module.id, module.stakingModuleAddress); + logger.table(operatorsDigests); } }); @@ -198,7 +198,7 @@ router }); const sortedKeys = activeKeys.sort((a, b) => a.activeKeys - b.activeKeys); - console.table(sortedKeys); + logger.table(sortedKeys); }); router @@ -230,5 +230,5 @@ router .description('returns rewards distribution') .action(async () => { const distribution = await stakingRouterContract.getStakingRewardsDistribution(); - console.log('distribution', distribution); + logger.log('Distribution', distribution); }); diff --git a/programs/tx.ts b/programs/tx.ts index b2e03e8..fd2a853 100644 --- a/programs/tx.ts +++ b/programs/tx.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { provider } from '@providers'; -import { buildTraceTree, formatTraceNode, getAllAbi, printTree } from '@utils'; +import { buildTraceTree, formatTraceNode, getAllAbi, logger, printTree } from '@utils'; import { parseEther } from 'ethers'; const tx = program.command('tx').description('transaction utils'); @@ -10,7 +10,7 @@ tx.command('get-tx') .argument('', 'transaction hash') .action(async (hash) => { const transaction = await provider.getTransaction(hash); - console.log(transaction); + logger.log(transaction); }); tx.command('parse-calldata') @@ -29,7 +29,7 @@ tx.command('parse-calldata') const result = iface.parseTransaction(tx); if (result) { - console.log(name, result); + logger.log(name, result); } }); }); @@ -43,7 +43,7 @@ tx.command('parse-method') abi.forEach(({ name, iface }) => { iface.forEachFunction((func) => { if (func.selector === selector) { - console.log(name, func); + logger.log(name, func); } }); }); @@ -59,7 +59,7 @@ tx.command('parse-error') const result = iface.parseError(reason); if (result) { - console.log(name, result); + logger.log(name, result); } }); }); diff --git a/programs/validators.ts b/programs/validators.ts index 1acc561..7ef2c17 100644 --- a/programs/validators.ts +++ b/programs/validators.ts @@ -12,6 +12,7 @@ import { import { deriveEth2ValidatorKeys, deriveKeyFromMnemonic } from '@chainsafe/bls-keygen'; import { AttestationDataBigint, computeDomain, signAttestationData } from '@consensus'; import { getBytes, hexlify } from 'ethers'; +import { logger } from '@utils'; const validators = program.command('validators').description('validators utils'); @@ -19,10 +20,10 @@ validators .command('0x00') .description('fetches lido validators with 0x00 withdraw credentials') .action(async () => { - console.log('fetching keys from KAPI, it may take a while...'); + logger.log('Fetching keys from KAPI, it may take a while...'); const keys = await fetchAllLidoKeys(); - console.log('fetching validators from CL, it may take a few minutes...'); + logger.log('Fetching validators from CL, it may take a few minutes...'); const validators = await fetchAllValidators(); const keysMap = keys.reduce( @@ -37,13 +38,13 @@ validators return keysMap[validator.pubkey]; }); - console.log('validators on CL', lidoValidators.length); + logger.log('Validators on CL', lidoValidators.length); const validatorsWith0x00WC = lidoValidators.filter(({ validator }) => { return validator.withdrawal_credentials.startsWith('0x00'); }); - console.log('validators with 0x00 wc', validatorsWith0x00WC.length); + logger.log('Validators with 0x00 wc', validatorsWith0x00WC.length); const nodeOperatorIds = validatorsWith0x00WC.reduce( (acc, { validator }) => { @@ -58,7 +59,7 @@ validators {} as Record, ); - console.log('operators with 0x00 wc', nodeOperatorIds); + logger.log('Operators with 0x00 wc', nodeOperatorIds); }); validators @@ -88,7 +89,7 @@ validators const epoch = String(Math.floor(slot / Number(spec.SLOTS_PER_EPOCH))); if (validator.slashed) { - console.warn(`validator is already slashed`); + logger.warn('Validator is already slashed'); return; } @@ -127,5 +128,5 @@ validators }; const result = await postToAttestationPool(attesterSlashing); - console.log(result); + logger.log(result); }); diff --git a/programs/voting.ts b/programs/voting.ts index e081957..15c4567 100644 --- a/programs/voting.ts +++ b/programs/voting.ts @@ -1,6 +1,6 @@ import { program } from '@command'; import { votingContract } from '@contracts'; -import { executeVote, voteAgainst, voteFor } from '@utils'; +import { executeVote, logger, voteAgainst, voteFor } from '@utils'; import { addLogsCommands, addParsingCommands } from './common'; const voting = program.command('voting').description('interact with voting contract'); @@ -13,7 +13,7 @@ voting .argument('', 'vote id') .action(async (voteId) => { const vote = await votingContract.getVote(voteId); - console.log('vote', vote.toObject()); + logger.log('Vote', vote.toObject()); }); voting @@ -21,7 +21,7 @@ voting .description('returns votes length') .action(async () => { const votes = await votingContract.votesLength(); - console.log('votes', Number(votes)); + logger.log('Votes', Number(votes)); }); voting @@ -32,7 +32,7 @@ voting .action(async (options) => { const { script, meta } = options; const voteId = await votingContract.newVote(script, meta); - console.log('vote id', Number(voteId)); + logger.log('Vote id', Number(voteId)); }); voting @@ -48,7 +48,7 @@ voting } else { await voteAgainst(voteId); } - console.log('voted'); + logger.log('Voted'); }); voting @@ -57,5 +57,5 @@ voting .argument('', 'vote id') .action(async (voteId) => { await executeVote(voteId); - console.log('executed'); + logger.log('Executed'); }); diff --git a/programs/withdrawal-request.ts b/programs/withdrawal-request.ts index 90f5866..1c7b009 100644 --- a/programs/withdrawal-request.ts +++ b/programs/withdrawal-request.ts @@ -9,7 +9,7 @@ import { addParsingCommands, addPauseUntilSubCommands, } from './common'; -import { contractCallTxWithConfirm } from '@utils'; +import { contractCallTxWithConfirm, logger } from '@utils'; const withdrawal = program.command('withdrawal-request').description('interact with withdrawal request contract'); addAccessControlSubCommands(withdrawal, withdrawalRequestContract); @@ -45,7 +45,7 @@ withdrawal .description('returns last finalized request id') .action(async () => { const lastFinalizedRequestId = await withdrawalRequestContract.getLastFinalizedRequestId(); - console.log('last finalized request id', lastFinalizedRequestId); + logger.log('Last finalized request id', lastFinalizedRequestId); }); withdrawal @@ -53,7 +53,7 @@ withdrawal .description('returns last request id') .action(async () => { const lastRequestId = await withdrawalRequestContract.getLastRequestId(); - console.log('last request id', lastRequestId); + logger.log('Last request id', lastRequestId); }); withdrawal @@ -63,7 +63,7 @@ withdrawal .action(async (options) => { const { address } = options; const requestIds = await withdrawalRequestContract.getWithdrawalRequests(address); - console.log('request ids', requestIds); + logger.log('Request ids', requestIds); }); withdrawal @@ -78,7 +78,7 @@ withdrawal const requests = await withdrawalRequestContract.getWithdrawalStatus(limitedRequestIds.toArray()); requests.forEach((request: Result) => { - console.log(request.toObject()); + logger.log(request.toObject()); }); }); @@ -106,9 +106,9 @@ withdrawal const filteredRequestsIds = filteredRequests.map((request) => request.id); if (filteredRequestsIds.length) { - console.log(filteredRequestsIds.join(',')); + logger.log(filteredRequestsIds.join(',')); } else { - console.log('no claimable requests'); + logger.log('No claimable requests'); } }); @@ -144,7 +144,7 @@ withdrawal .description('returns if bunker mode is active') .action(async () => { const isBunker = await withdrawalRequestContract.isBunkerModeActive(); - console.log('bunker', isBunker); + logger.log('Bunker', isBunker); }); withdrawal @@ -153,9 +153,9 @@ withdrawal .action(async () => { const timestamp = await withdrawalRequestContract.bunkerModeSinceTimestamp(); if (timestamp == MaxUint256) { - console.log('bunker is not started'); + logger.log('Bunker is not started'); } else { - console.log('bunker start', new Date(Number(timestamp) * 1000)); + logger.log('Bunker start', new Date(Number(timestamp) * 1000)); } }); @@ -164,7 +164,7 @@ withdrawal .description('returns unfinalized stETH') .action(async () => { const unfinalizedStETH = await withdrawalRequestContract.unfinalizedStETH(); - console.log('unfinalized stETH', formatEther(unfinalizedStETH)); + logger.log('Unfinalized stETH', formatEther(unfinalizedStETH)); }); withdrawal @@ -188,7 +188,7 @@ withdrawal const formattedResult = result.toObject(); formattedResult.batches = formattedResult.batches.filter((v: unknown) => !!v); - console.log('result', formattedResult); + logger.log('Result', formattedResult); }); withdrawal @@ -198,7 +198,7 @@ withdrawal .action(async (options) => { const { address } = options; const requests = await withdrawalRequestContract.getWithdrawalRequests(address); - console.log('requests', requests); + logger.log('Requests', requests); }); withdrawal @@ -206,5 +206,5 @@ withdrawal .description('returns max batches length') .action(async () => { const mxaBatches = await withdrawalRequestContract.MAX_BATCHES_LENGTH(); - console.log('max batches', mxaBatches); + logger.log('Max batches', mxaBatches); }); diff --git a/scripts/agent-or-direct.ts b/scripts/agent-or-direct.ts index 0803613..6fb78ca 100644 --- a/scripts/agent-or-direct.ts +++ b/scripts/agent-or-direct.ts @@ -1,4 +1,4 @@ -import { CallScriptAction, authorizedCallTest, encodeCallScript } from '@utils'; +import { CallScriptAction, authorizedCallTest, encodeCallScript, logger } from '@utils'; import { aragonAgentAddress, votingAddress } from '@contracts'; import { Contract } from 'ethers'; import { agentForward } from './agent'; @@ -6,8 +6,7 @@ import chalk from 'chalk'; import prompts from 'prompts'; const printCallSuccess = (from: string) => { - console.log(chalk`{green successfully called from {bold ${from}}, added to the list}`); - console.log(''); + logger.success(`Successfully called from: ${chalk.bold(from)}, call added to the script\n`); }; export const agentOrDirect = async (contract: Contract, method: string, args: unknown[] = []) => { @@ -36,8 +35,7 @@ export const agentOrDirect = async (contract: Contract, method: string, args: un errors.push(error); } - console.log(''); - console.warn(chalk`{red calls from voting and agent failed}`); + logger.error('\nCalls from voting and agent failed'); const from = await promptFrom(); @@ -49,23 +47,23 @@ export const agentOrDirect = async (contract: Contract, method: string, args: un return encodeFromVoting(call); } - console.dir(errors, { depth: null }); - throw new Error('aborted'); + logger.error(errors); + throw new Error('Aborted'); }; export const promptFrom = async () => { const { from } = await prompts({ type: 'select', name: 'from', - message: 'what to do?', + message: 'What to do?', choices: [ - { title: chalk`abort and show errors`, value: null }, + { title: chalk`Abort and show errors`, value: null }, { - title: chalk`add as a direct call {red (only choose if you know what you are doing)}`, + title: chalk`Add as a direct call {red (only choose if you know what you are doing)}`, value: 'voting', }, { - title: chalk`add as a forwarded call from agent {red (only choose if you know what you are doing)}`, + title: chalk`Add as a forwarded call from agent {red (only choose if you know what you are doing)}`, value: 'agent', }, ], diff --git a/utils/authorized-call.ts b/utils/authorized-call.ts index 0505fef..c49f750 100644 --- a/utils/authorized-call.ts +++ b/utils/authorized-call.ts @@ -1,23 +1,21 @@ import { Contract } from 'ethers'; import { votingForward } from '@scripts'; -import { green } from 'chalk'; import { aragonAgentAddress, votingAddress } from '@contracts'; import { encodeCallScript } from './scripts'; import { forwardVoteFromTm } from './voting'; import { contractCallTxWithConfirm } from './call-tx'; import { agentForward } from 'scripts/agent'; -import { printTx } from './print-tx'; import { getProvider, getSignerAddress } from './contract'; +import { logger } from './logger'; export const authorizedCall = async (contract: Contract, method: string, args: unknown[] = []) => { - printTx(contract, method, args); const errors = []; try { const passed = await authorizedCallEOA(contract, method, args); if (passed) return; } catch (error) { - console.warn('direct call failed, trying to forward to the voting'); + logger.warn('Direct call failed, trying to forward to the voting'); errors.push(error); } @@ -25,7 +23,7 @@ export const authorizedCall = async (contract: Contract, method: string, args: u const passed = await authorizedCallVoting(contract, method, args); if (passed) return; } catch (error) { - console.warn('call from voting failed'); + logger.warn('Call from voting failed'); errors.push(error); } @@ -33,11 +31,11 @@ export const authorizedCall = async (contract: Contract, method: string, args: u const passed = await authorizedCallAgent(contract, method, args); if (passed) return; } catch (error) { - console.warn('call from agent failed'); + logger.warn('Call from agent failed'); errors.push(error); } - console.log(errors); + logger.error(errors); }; export const authorizedCallEOA = async (contract: Contract, method: string, args: unknown[] = []) => { @@ -81,7 +79,7 @@ export const authorizedCallTest = async (contract: Contract, method: string, arg }; const printSuccess = (from: string) => { - console.log(green(`\ncall from ${from} passed successfully`)); + logger.success(`\nCall from ${from} passed successfully`); }; const encode = async (contract: Contract, method: string, args: unknown[] = []) => { diff --git a/utils/call-tx.ts b/utils/call-tx.ts index ebbd63a..6567ef7 100644 --- a/utils/call-tx.ts +++ b/utils/call-tx.ts @@ -1,14 +1,29 @@ -import chalk from 'chalk'; import { Contract, ContractTransaction, ContractTransactionResponse } from 'ethers'; import { confirmTx } from './confirm-tx'; +import { printTx } from './print-tx'; +import { logger } from './logger'; export const contractCallTxWithConfirm = async (contract: Contract, method: string, args: unknown[]) => { + await printTx(contract, method, args); + await contractStaticCallTx(contract, method, args); + const confirmed = await confirmTx(); if (!confirmed) return null; return await contractCallTx(contract, method, args); }; +export const contractStaticCallTx = async (contract: Contract, method: string, args: unknown[]) => { + const contractAddress = await contract.getAddress(); + + try { + const result = await contract[method].staticCall(...args); + logger.success(`Successfully called ${method} on ${contractAddress}. Result:`, result); + } catch (error) { + logger.error(`Failed to call ${method} on ${contractAddress}. Error:`, error); + } +}; + export const populateGasLimit = async (contract: Contract, method: string, argsWithOverrides: unknown[]) => { const fragment = contract.interface.getFunction(method, argsWithOverrides); @@ -35,9 +50,9 @@ export const populateGasLimit = async (contract: Contract, method: string, argsW export const contractCallTx = async (contract: Contract, method: string, args: unknown[]) => { const argsWithGasLimit = await populateGasLimit(contract, method, args); const tx: ContractTransactionResponse = await contract[method](...argsWithGasLimit); - console.log('tx sent', chalk.green(tx.hash)); + logger.success('Tx sent', tx.hash); - console.log('waiting for tx to be mined...'); + logger.log('Waiting for tx to be mined...'); const receipt = await tx.wait(); if (!receipt) { @@ -45,17 +60,18 @@ export const contractCallTx = async (contract: Contract, method: string, args: u } try { - console.log('tx logs:'); + logger.log('Tx logs:'); receipt.logs.forEach((log) => { const parsedLog = contract.interface.parseLog({ data: log.data, topics: log.topics as string[], }); - console.dir(parsedLog, { depth: null }); + + logger.dir(parsedLog, { depth: null }); }); } catch (error) { - console.log('failed to parse logs'); + logger.error('Failed to parse logs', error); } return [tx, receipt] as const; diff --git a/utils/compare-calls.ts b/utils/compare-calls.ts index c09093a..dee35c1 100644 --- a/utils/compare-calls.ts +++ b/utils/compare-calls.ts @@ -1,4 +1,5 @@ import { Contract } from 'ethers'; +import { logger } from './logger'; export type ContractCalls = { method: string; args?: unknown[] }; @@ -27,5 +28,5 @@ export const compareContractCalls = async (contracts: Contract[], calls: Contrac result.push({ ...row, matched }); } - console.table(result); + logger.table(result); }; diff --git a/utils/confirm-tx.ts b/utils/confirm-tx.ts index ca30cd1..3d40391 100644 --- a/utils/confirm-tx.ts +++ b/utils/confirm-tx.ts @@ -4,7 +4,7 @@ export const confirmTx = async () => { const { confirm } = await prompts({ type: 'confirm', name: 'confirm', - message: 'confirm sending transaction?', + message: 'Confirm sending transaction?', initial: true, }); diff --git a/utils/index.ts b/utils/index.ts index abcafdd..3933564 100644 --- a/utils/index.ts +++ b/utils/index.ts @@ -7,6 +7,7 @@ export * from './contract'; export * from './csv'; export * from './format-date'; export * from './get-value'; +export * from './logger'; export * from './modules'; export * from './parse-method-call'; export * from './print-tx'; diff --git a/utils/logger.ts b/utils/logger.ts new file mode 100644 index 0000000..9ddac79 --- /dev/null +++ b/utils/logger.ts @@ -0,0 +1,41 @@ +import { green, yellow, red } from 'chalk'; +import { stringify } from './stringify'; + +class Logger { + dir = console.dir; + log = console.log; + table = console.table; + + success(...args: unknown[]) { + console.log( + ...args.map((arg) => { + if (typeof arg === 'string') return green(arg); + if (typeof arg === 'object') return green(stringify(arg, 2)); + return green(String(arg)); + }), + ); + } + + warn(...args: unknown[]) { + console.warn( + ...args.map((arg) => { + if (typeof arg === 'string') return yellow(arg); + if (typeof arg === 'object') return yellow(stringify(arg, 2)); + return yellow(String(arg)); + }), + ); + } + + error(...args: unknown[]) { + console.error( + ...args.map((arg) => { + if (arg instanceof Error) return red(arg.message); + if (typeof arg === 'string') return red(arg); + if (typeof arg === 'object') return red(stringify(arg, 2)); + return red(String(arg)); + }), + ); + } +} + +export const logger = new Logger(); diff --git a/utils/print-tx.ts b/utils/print-tx.ts index b273c78..055656f 100644 --- a/utils/print-tx.ts +++ b/utils/print-tx.ts @@ -2,8 +2,10 @@ import chalk from 'chalk'; import { Contract } from 'ethers'; import { stringify } from './stringify'; import { getProvider, getSignerAddress } from './contract'; +import { logger } from './logger'; const title = chalk.gray; +const chain = chalk.green.bold; const value = chalk.blue.bold; export const printTx = async (contract: Contract, method: string, args: unknown[] = []) => { @@ -17,9 +19,9 @@ export const printTx = async (contract: Contract, method: string, args: unknown[ const call = `${method}(${parsedArgs})`; const data = contract.interface.encodeFunctionData(method, args); - console.log(title('chain:'), value(network.name)); - console.log(title(' from:'), value(from)); - console.log(title(' to:'), value(to)); - console.log(title(' call:'), value(call)); - console.log(title(' data:'), value(data)); + logger.log(title('Chain:'), chain(network.name)); + logger.log(title(' From:'), value(from)); + logger.log(title(' To:'), value(to)); + logger.log(title(' Call:'), value(call)); + logger.log(title(' Data:'), value(data)); }; diff --git a/utils/stringify.ts b/utils/stringify.ts index 62a75e0..63969cb 100644 --- a/utils/stringify.ts +++ b/utils/stringify.ts @@ -1,3 +1,3 @@ -export const stringify = (input: unknown) => { - return JSON.stringify(input, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)); +export const stringify = (input: unknown, space?: string | number) => { + return JSON.stringify(input, (_key, value) => (typeof value === 'bigint' ? value.toString() : value), space); }; diff --git a/utils/tree.ts b/utils/tree.ts index 85da1e4..f6ea25f 100644 --- a/utils/tree.ts +++ b/utils/tree.ts @@ -1,4 +1,5 @@ import chalk from 'chalk'; +import { logger } from './logger'; export class TreeNode { constructor( @@ -47,7 +48,7 @@ export const printTree = ( lines.forEach((line, index) => { const separator = chalk.gray(getLineIndent(index)); - console.log(`${indent}${separator}${line}`); + logger.log(`${indent}${separator}${line}`); }); indent += chalk.gray(isLastChild ? ' ' : '│ '); diff --git a/utils/voting.ts b/utils/voting.ts index 7877ca7..341346f 100644 --- a/utils/voting.ts +++ b/utils/voting.ts @@ -2,11 +2,12 @@ import { tmContract, votingContract } from '@contracts'; import { sleep } from './sleep'; import { contractCallTx, contractCallTxWithConfirm } from './call-tx'; import { getSignerAddress } from './contract'; +import { logger } from './logger'; export const forwardVoteFromTm = async (votingCalldata: string) => { const tx = await contractCallTxWithConfirm(tmContract, 'forward', [votingCalldata]); if (tx == null) return; - console.log('vote started'); + logger.success('Vote started'); await voteLastVoting(); }; @@ -16,19 +17,19 @@ export const voteLastVoting = async () => { const lastVoteId = Number(votesLength) - 1; if (lastVoteId == -1) { - console.warn('no votes'); + logger.warn('No votes'); return; } const lastVote = await votingContract.getVote(lastVoteId); if (lastVote.open == false) { - console.warn('vote is not open'); + logger.warn('Vote is not open'); return; } if (Number(lastVote.phase) !== 0) { - console.warn('wrong phase'); + logger.warn('Wrong phase'); return; } @@ -39,17 +40,17 @@ export const voteLastVoting = async () => { export const voteFor = async (voteId: number) => { await contractCallTx(votingContract, 'vote', [voteId, true, false]); - console.log('vote voted'); + logger.success('Vote voted'); }; export const voteAgainst = async (voteId: number) => { await contractCallTx(votingContract, 'vote', [voteId, false, false]); - console.log('vote voted'); + logger.success('Vote voted'); }; export const executeVote = async (voteId: number) => { await contractCallTx(votingContract, 'executeVote', [voteId]); - console.log('vote executed'); + logger.success('Vote executed'); }; export const waitForEnd = async (voteId: number) => { @@ -58,7 +59,7 @@ export const waitForEnd = async (voteId: number) => { const vote = await votingContract.getVote(voteId); if (vote.open == true) { - console.log('waiting for the vote to finish, still active'); + logger.log('Waiting for the vote to finish, still active'); await waitForEnd(voteId); } }; @@ -68,7 +69,7 @@ export const checkTmCanForward = async () => { const canForward = await tmContract.canForward(signerAddress, '0x'); if (!canForward) { - console.warn('tm can not forward, check your LDO balance'); + logger.warn('TM can not forward, check your LDO balance'); return false; } diff --git a/utils/write-to-file.ts b/utils/write-to-file.ts index e83d66e..669e4cd 100644 --- a/utils/write-to-file.ts +++ b/utils/write-to-file.ts @@ -1,8 +1,8 @@ -import chalk from 'chalk'; import { writeFile, access, mkdir } from 'fs/promises'; import { constants } from 'fs'; import prompts from 'prompts'; import { dirname } from 'path'; +import { logger } from './logger'; const isFileExists = async (filePath: string) => { try { @@ -13,23 +13,21 @@ const isFileExists = async (filePath: string) => { } }; -const warn = chalk.yellow; - export const writeToFile = async (filePath: string, fileContent: string) => { const isExist = await isFileExists(filePath); if (isExist) { - console.log(warn(`file ${filePath} already exists`)); + logger.warn(`File ${filePath} already exists`); const { confirm } = await prompts({ type: 'confirm', name: 'confirm', - message: 'do you want to rewrite it?', + message: 'Do you want to rewrite it?', initial: true, }); if (!confirm) { - console.log('file not saved'); + logger.warn('File not saved'); return; } } @@ -37,8 +35,8 @@ export const writeToFile = async (filePath: string, fileContent: string) => { try { await mkdir(dirname(filePath), { recursive: true }); await writeFile(filePath, fileContent); - console.log('file saved to', filePath); + logger.success(`File saved to ${filePath}`); } catch (error) { - console.error(error); + logger.error('Failed to save file', error); } };