Skip to content

Commit

Permalink
feat: multisig-mon
Browse files Browse the repository at this point in the history
  • Loading branch information
felipe-op committed Nov 9, 2023
1 parent d798e07 commit b32937d
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 46 deletions.
12 changes: 12 additions & 0 deletions packages/chain-mon/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ BALANCE_MON__RPC=
# JSON array in the format [{ "address": <address>, "nickname": <nickname> }, ... ]
BALANCE_MON__ACCOUNTS=


###############################################################################
# ↓ multisig-mon ↓ #
###############################################################################

# RPC pointing to network to monitor balances on
MULTISIG_MON__RPC=

# JSON array in the format [{ "address": <address>, "nickname": <nickname> }, ... ]
MULTISIG_MON__ACCOUNTS=


###############################################################################
# ↓ wallet-mon ↓ #
###############################################################################
Expand Down
12 changes: 8 additions & 4 deletions packages/chain-mon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@
],
"scripts": {
"dev:balance-mon": "tsx watch ./src/balance-mon/service.ts",
"dev:wallet-mon": "tsx watch ./src/wallet-mon/service.ts",
"dev:drippie-mon": "tsx watch ./src/drippie-mon/service.ts",
"dev:wd-mon": "tsx watch ./src/wd-mon/service.ts",
"dev:fault-mon": "tsx watch ./src/fault-mon/service.ts",
"dev:multisig-mon": "tsx watch ./src/multisig-mon/service.ts",
"dev:replica-mon": "tsx watch ./src/replica-mon/service.ts",
"dev:wallet-mon": "tsx watch ./src/wallet-mon/service.ts",
"dev:wd-mon": "tsx watch ./src/wd-mon/service.ts",

"start:balance-mon": "tsx ./src/balance-mon/service.ts",
"start:wallet-mon": "tsx ./src/wallet-mon/service.ts",
"start:drippie-mon": "tsx ./src/drippie-mon/service.ts",
"start:wd-mon": "tsx ./src/wd-mon/service.ts",
"start:fault-mon": "tsx ./src/fault-mon/service.ts",
"start:multisig-mon": "tsx ./src/multisig-mon/service.ts",
"start:replica-mon": "tsx ./src/replica-mon/service.ts",
"start:wallet-mon": "tsx ./src/wallet-mon/service.ts",
"start:wd-mon": "tsx ./src/wd-mon/service.ts",

"test": "hardhat test",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json",
"build": "tsc -p ./tsconfig.json",
Expand Down
42 changes: 1 addition & 41 deletions packages/chain-mon/src/balance-mon/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import {
validators,
} from '@eth-optimism/common-ts'
import { Provider } from '@ethersproject/abstract-provider'
import { BigNumber, ethers } from 'ethers'

import Safe from '../abi/IGnosisSafe.0.8.19.json'
import { version } from '../../package.json'

type BalanceMonOptions = {
Expand All @@ -18,12 +16,11 @@ type BalanceMonOptions = {

type BalanceMonMetrics = {
balances: Gauge
safeNonces: Gauge
unexpectedRpcErrors: Counter
}

type BalanceMonState = {
accounts: Array<{ address: string; nickname: string; safe: boolean }>
accounts: Array<{ address: string; nickname: string }>
}

export class BalanceMonService extends BaseServiceV2<
Expand Down Expand Up @@ -57,11 +54,6 @@ export class BalanceMonService extends BaseServiceV2<
desc: 'Balances of addresses',
labels: ['address', 'nickname'],
},
safeNonces: {
type: Gauge,
desc: 'Safe nonce',
labels: ['address', 'nickname'],
},
unexpectedRpcErrors: {
type: Counter,
desc: 'Number of unexpected RPC errors',
Expand Down Expand Up @@ -103,38 +95,6 @@ export class BalanceMonService extends BaseServiceV2<
name: 'getBalance',
})
}

// Get the safe nonce to report
if (account.safe) {
try {
const safeContract = new ethers.Contract(
account.address,
Safe.abi,
this.options.rpc
)
const safeNonce = BigNumber.from(await safeContract.nonce())
this.logger.info(`got nonce`, {
address: account.address,
nickname: account.nickname,
nonce: safeNonce.toString(),
})

this.metrics.safeNonces.set(
{ address: account.address, nickname: account.nickname },
parseInt(safeNonce.toString(), 10)
)
} catch (err) {
this.logger.info(`got unexpected RPC error`, {
section: 'safeNonce',
name: 'getSafeNonce',
err,
})
this.metrics.unexpectedRpcErrors.inc({
section: 'safeNonce',
name: 'getSafeNonce',
})
}
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/chain-mon/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './balance-mon/service'
export * from './drippie-mon/service'
export * from './fault-mon/index'
export * from './multisig-mon/service'
export * from './wd-mon/service'
export * from './wallet-mon/service'
export * from './fault-mon/index'
109 changes: 109 additions & 0 deletions packages/chain-mon/src/multisig-mon/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
BaseServiceV2,
StandardOptions,
Gauge,
Counter,
validators,
} from '@eth-optimism/common-ts'
import { Provider } from '@ethersproject/abstract-provider'
import { BigNumber, ethers } from 'ethers'

import Safe from '../abi/IGnosisSafe.0.8.19.json'
import { version } from '../../package.json'

type MultisigMonOptions = {
rpc: Provider
accounts: string
}

type MultisigMonMetrics = {
safeNonce: Gauge
unexpectedRpcErrors: Counter
}

type MultisigMonState = {
accounts: Array<{ address: string; nickname: string }>
}

export class MultisigMonService extends BaseServiceV2<
MultisigMonOptions,
MultisigMonMetrics,
MultisigMonState
> {
constructor(options?: Partial<MultisigMonOptions & StandardOptions>) {
super({
version,
name: 'multisig-mon',
loop: true,
options: {
loopIntervalMs: 60_000,
...options,
},
optionsSpec: {
rpc: {
validator: validators.provider,
desc: 'Provider for network to monitor balances on',
},
accounts: {
validator: validators.str,
desc: 'JSON array of [{ address, nickname, safe }] to monitor balances and nonces of',
public: true,
},
},
metricsSpec: {
safeNonce: {
type: Gauge,
desc: 'Safe nonce',
labels: ['address', 'nickname'],
},
unexpectedRpcErrors: {
type: Counter,
desc: 'Number of unexpected RPC errors',
labels: ['section', 'name'],
},
},
})
}

protected async init(): Promise<void> {
this.state.accounts = JSON.parse(this.options.accounts)
}

protected async main(): Promise<void> {
for (const account of this.state.accounts) {
try {
const safeContract = new ethers.Contract(
account.address,
Safe.abi,
this.options.rpc
)
const safeNonce = BigNumber.from(await safeContract.nonce())
this.logger.info(`got nonce`, {
address: account.address,
nickname: account.nickname,
nonce: safeNonce.toString(),
})

this.metrics.safeNonce.set(
{ address: account.address, nickname: account.nickname },
parseInt(safeNonce.toString(), 10)
)
} catch (err) {
this.logger.info(`got unexpected RPC error`, {
section: 'safeNonce',
name: 'getSafeNonce',
err,
})
this.metrics.unexpectedRpcErrors.inc({
section: 'safeNonce',
name: 'getSafeNonce',
})
}
}
}
}

if (require.main === module) {
const service = new MultisigMonService()
service.run()
}

0 comments on commit b32937d

Please sign in to comment.