Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
d6388be4
Commit
d6388be4
authored
Jun 01, 2023
by
Maurelian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(c-mon): Add wallet-mon service
parent
a1cbc77d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
209 additions
and
0 deletions
+209
-0
moody-foxes-enjoy.md
.changeset/moody-foxes-enjoy.md
+6
-0
Dockerfile.packages
ops/docker/Dockerfile.packages
+4
-0
.env.example
packages/chain-mon/.env.example
+10
-0
package.json
packages/chain-mon/package.json
+2
-0
index.ts
packages/chain-mon/src/index.ts
+1
-0
service.ts
packages/chain-mon/src/wallet-mon/service.ts
+175
-0
misc.ts
packages/core-utils/src/common/misc.ts
+11
-0
No files found.
.changeset/moody-foxes-enjoy.md
0 → 100644
View file @
d6388be4
---
'
@eth-optimism/chain-mon'
:
minor
'
@eth-optimism/core-utils'
:
patch
---
Added a new service wallet-mon to identify unexpected transfers from key accounts
ops/docker/Dockerfile.packages
View file @
d6388be4
...
@@ -89,3 +89,7 @@ ENTRYPOINT ["npm", "run", "start:drippie-mon"]
...
@@ -89,3 +89,7 @@ ENTRYPOINT ["npm", "run", "start:drippie-mon"]
FROM base as wd-mon
FROM base as wd-mon
WORKDIR /opt/optimism/packages/chain-mon
WORKDIR /opt/optimism/packages/chain-mon
ENTRYPOINT ["yarn", "run", "start:wd-mon"]
ENTRYPOINT ["yarn", "run", "start:wd-mon"]
FROM base as wallet-mon
WORKDIR /opt/optimism/packages/chain-mon
ENTRYPOINT ["yarn", "run", "start:wallet-mon"]
packages/chain-mon/.env.example
View file @
d6388be4
...
@@ -8,6 +8,16 @@ BALANCE_MON__RPC=
...
@@ -8,6 +8,16 @@ BALANCE_MON__RPC=
# JSON array in the format [{ "address": <address>, "nickname": <nickname> }, ... ]
# JSON array in the format [{ "address": <address>, "nickname": <nickname> }, ... ]
BALANCE_MON__ACCOUNTS=
BALANCE_MON__ACCOUNTS=
###############################################################################
# ↓ wallet-mon ↓ #
###############################################################################
# RPC pointing to network to monitor
WALLET_MON__RPC=
# The block number to start monitoring from
WALLET_MON__START_BLOCK_NUMBER=
###############################################################################
###############################################################################
# ↓ drippie-mon ↓ #
# ↓ drippie-mon ↓ #
###############################################################################
###############################################################################
...
...
packages/chain-mon/package.json
View file @
d6388be4
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
],
],
"scripts"
:
{
"scripts"
:
{
"start:balance-mon"
:
"ts-node ./src/balance-mon/service.ts"
,
"start:balance-mon"
:
"ts-node ./src/balance-mon/service.ts"
,
"start:wallet-mon"
:
"ts-node ./src/wallet-mon/service.ts"
,
"start:drippie-mon"
:
"ts-node ./src/drippie-mon/service.ts"
,
"start:drippie-mon"
:
"ts-node ./src/drippie-mon/service.ts"
,
"start:wd-mon"
:
"ts-node ./src/wd-mon/service.ts"
,
"start:wd-mon"
:
"ts-node ./src/wd-mon/service.ts"
,
"test:coverage"
:
"echo 'No tests defined.'"
,
"test:coverage"
:
"echo 'No tests defined.'"
,
...
@@ -35,6 +36,7 @@
...
@@ -35,6 +36,7 @@
"dependencies"
:
{
"dependencies"
:
{
"@eth-optimism/common-ts"
:
"0.8.1"
,
"@eth-optimism/common-ts"
:
"0.8.1"
,
"@eth-optimism/contracts-periphery"
:
"1.0.8"
,
"@eth-optimism/contracts-periphery"
:
"1.0.8"
,
"@eth-optimism/contracts-bedrock"
:
"0.14.0"
,
"@eth-optimism/core-utils"
:
"0.12.0"
,
"@eth-optimism/core-utils"
:
"0.12.0"
,
"@eth-optimism/sdk"
:
"2.1.0"
,
"@eth-optimism/sdk"
:
"2.1.0"
,
"ethers"
:
"^5.7.0"
,
"ethers"
:
"^5.7.0"
,
...
...
packages/chain-mon/src/index.ts
View file @
d6388be4
export
*
from
'
./balance-mon/service
'
export
*
from
'
./balance-mon/service
'
export
*
from
'
./drippie-mon/service
'
export
*
from
'
./drippie-mon/service
'
export
*
from
'
./wd-mon/service
'
export
*
from
'
./wd-mon/service
'
export
*
from
'
./wallet-mon/service
'
packages/chain-mon/src/wallet-mon/service.ts
0 → 100644
View file @
d6388be4
import
{
BaseServiceV2
,
StandardOptions
,
Gauge
,
Counter
,
validators
,
waitForProvider
,
}
from
'
@eth-optimism/common-ts
'
import
{
getChainId
,
compareAddrs
}
from
'
@eth-optimism/core-utils
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
mainnetConfig
from
'
@eth-optimism/contracts-bedrock/deploy-config/mainnet.json
'
import
goerliConfig
from
'
@eth-optimism/contracts-bedrock/deploy-config/goerli.json
'
import
l2OutputOracleArtifactsMainnet
from
'
@eth-optimism/contracts-bedrock/deployments/mainnet/L2OutputOracleProxy.json
'
import
l2OutputOracleArtifactsGoerli
from
'
@eth-optimism/contracts-bedrock/deployments/goerli/L2OutputOracleProxy.json
'
import
{
version
}
from
'
../../package.json
'
const
networks
=
{
1
:
'
mainnet
'
,
10
:
'
goerli
'
,
}
const
bedrockAccounts
=
{
mainnet
:
[
{
label
:
'
Proposer
'
,
wallet
:
mainnetConfig
.
l2OutputOracleProposer
,
target
:
l2OutputOracleArtifactsMainnet
.
address
,
},
{
label
:
'
Batcher
'
,
wallet
:
mainnetConfig
.
batchSenderAddress
,
target
:
mainnetConfig
.
batchInboxAddress
,
},
],
goerli
:
[
{
label
:
'
Proposer
'
,
wallet
:
goerliConfig
.
l2OutputOracleProposer
,
target
:
l2OutputOracleArtifactsGoerli
.
address
,
},
{
label
:
'
Batcher
'
,
wallet
:
goerliConfig
.
batchSenderAddress
,
target
:
goerliConfig
.
batchInboxAddress
,
},
],
}
type
TransferMonOptions
=
{
rpc
:
Provider
startBlockNumber
:
number
}
type
TransferMonMetrics
=
{
validatedCalls
:
Counter
unexpectedCalls
:
Counter
unexpectedRpcErrors
:
Counter
}
type
TransferMonState
=
{
chainId
:
number
highestUncheckedBlockNumber
:
number
}
export
class
TransferMonService
extends
BaseServiceV2
<
TransferMonOptions
,
TransferMonMetrics
,
TransferMonState
>
{
constructor
(
options
?:
Partial
<
TransferMonOptions
&
StandardOptions
>
)
{
super
({
version
,
name
:
'
transfer-mon
'
,
loop
:
true
,
options
:
{
loopIntervalMs
:
60
_000
,
...
options
,
},
optionsSpec
:
{
rpc
:
{
validator
:
validators
.
provider
,
desc
:
'
Provider for network to monitor balances on
'
,
},
startBlockNumber
:
{
validator
:
validators
.
num
,
default
:
-
1
,
desc
:
'
L1 block number to start checking from
'
,
public
:
true
,
},
},
metricsSpec
:
{
validatedCalls
:
{
type
:
Gauge
,
desc
:
'
Transactions from the account checked
'
,
labels
:
[
'
wallet
'
,
'
target
'
,
'
nickname
'
],
},
unexpectedCalls
:
{
type
:
Counter
,
desc
:
'
Number of unexpected transfers
'
,
labels
:
[
'
wallet
'
,
'
target
'
,
'
nickname
'
],
},
unexpectedRpcErrors
:
{
type
:
Counter
,
desc
:
'
Number of unexpected RPC errors
'
,
labels
:
[
'
section
'
,
'
name
'
],
},
},
})
}
protected
async
init
():
Promise
<
void
>
{
// Connect to L1.
await
waitForProvider
(
this
.
options
.
rpc
,
{
logger
:
this
.
logger
,
name
:
'
L1
'
,
})
this
.
state
.
chainId
=
await
getChainId
(
this
.
options
.
rpc
)
if
(
this
.
options
.
startBlockNumber
===
-
1
)
{
this
.
state
.
highestUncheckedBlockNumber
=
await
this
.
options
.
rpc
.
getBlockNumber
()
}
else
{
this
.
state
.
highestUncheckedBlockNumber
=
this
.
options
.
startBlockNumber
}
}
protected
async
main
():
Promise
<
void
>
{
// get the next unchecked block
const
network
=
networks
[
this
.
state
.
chainId
]
const
accounts
=
bedrockAccounts
[
network
]
const
block
=
await
this
.
options
.
rpc
.
getBlock
(
this
.
state
.
highestUncheckedBlockNumber
)
for
(
const
txHash
of
block
.
transactions
)
{
for
(
const
account
of
accounts
)
{
const
tx
=
await
this
.
options
.
rpc
.
getTransaction
(
txHash
)
if
(
compareAddrs
(
account
.
wallet
,
tx
.
from
))
{
if
(
compareAddrs
(
account
.
target
,
tx
.
to
))
{
this
.
metrics
.
validatedCalls
.
inc
({
label
:
account
.
label
,
wallet
:
account
.
address
,
target
:
account
.
target
,
})
this
.
logger
.
info
(
'
validated call
'
,
{
label
:
account
.
label
,
wallet
:
account
.
address
,
target
:
account
.
target
,
})
}
else
{
this
.
metrics
.
unexpectedCalls
.
inc
({
label
:
account
.
label
,
wallet
:
account
.
address
,
target
:
tx
.
to
,
})
this
.
logger
.
error
(
'
Unexpected call detected
'
,
{
label
:
account
.
label
,
address
:
account
.
address
,
target
:
tx
.
to
,
})
}
}
}
}
}
}
if
(
require
.
main
===
module
)
{
const
service
=
new
TransferMonService
()
service
.
run
()
}
packages/core-utils/src/common/misc.ts
View file @
d6388be4
...
@@ -48,3 +48,14 @@ export const reqenv = (name: string): string => {
...
@@ -48,3 +48,14 @@ export const reqenv = (name: string): string => {
export
const
getenv
=
(
name
:
string
,
fallback
?:
string
):
string
|
undefined
=>
{
export
const
getenv
=
(
name
:
string
,
fallback
?:
string
):
string
|
undefined
=>
{
return
process
.
env
[
name
]
||
fallback
return
process
.
env
[
name
]
||
fallback
}
}
/**
* Returns true if the given string is a valid address.
*
* @param a First address to check.
* @param b Second address to check.
* @returns True if the given addresses match.
*/
export
const
compareAddrs
=
(
a
:
string
,
b
:
string
):
boolean
=>
{
return
a
.
toLowerCase
()
===
b
.
toLowerCase
()
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment