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
e422c544
Unverified
Commit
e422c544
authored
Sep 21, 2023
by
mergify[bot]
Committed by
GitHub
Sep 21, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into dependabot/npm_and_yarn/envalid-8.0.0
parents
d41133c8
15dfa313
Changes
28
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
1115 additions
and
520 deletions
+1115
-520
Dockerfile
indexer/Dockerfile
+1
-1
cli.go
indexer/cmd/indexer/cli.go
+0
-37
config.go
indexer/config/config.go
+8
-6
devnet.go
indexer/config/devnet.go
+40
-0
presets.go
indexer/config/presets.go
+6
-0
agent.go
op-challenger/game/fault/agent.go
+4
-1
agent_test.go
op-challenger/game/fault/agent_test.go
+5
-3
player.go
op-challenger/game/fault/player.go
+5
-1
coordinator.go
op-challenger/game/scheduler/coordinator.go
+6
-1
coordinator_test.go
op-challenger/game/scheduler/coordinator_test.go
+8
-1
scheduler.go
op-challenger/game/scheduler/scheduler.go
+18
-1
types.go
op-challenger/game/scheduler/types.go
+1
-0
worker.go
op-challenger/game/scheduler/worker.go
+3
-1
worker_test.go
op-challenger/game/scheduler/worker_test.go
+33
-1
metrics.go
op-challenger/metrics/metrics.go
+45
-0
noop.go
op-challenger/metrics/noop.go
+7
-0
main.py
ops/check-changed/main.py
+1
-5
pnpm-lock.yaml
pnpm-lock.yaml
+26
-22
docker-compose.yml
ufm-test-services/docker-compose.yml
+2
-1
metamask.json
ufm-test-services/grafana/dashboards/metamask.json
+182
-0
all.yml
ufm-test-services/grafana/provisioning/dashboards/all.yml
+9
-0
datasources.yml
...services/grafana/provisioning/datasources/datasources.yml
+0
-0
README.md
ufm-test-services/metamask/README.md
+30
-0
package.json
ufm-test-services/metamask/package.json
+5
-1
pnpm-lock.yaml
ufm-test-services/metamask/pnpm-lock.yaml
+525
-424
metamask.spec.ts
ufm-test-services/metamask/tests/metamask.spec.ts
+43
-12
prometheusUtils.ts
ufm-test-services/metamask/tests/prometheusUtils.ts
+101
-0
prometheus.yml
ufm-test-services/prometheus.yml
+1
-1
No files found.
indexer/Dockerfile
View file @
e422c544
...
@@ -23,4 +23,4 @@ FROM alpine:3.18
...
@@ -23,4 +23,4 @@ FROM alpine:3.18
COPY
--from=builder /app/indexer/indexer /usr/local/bin
COPY
--from=builder /app/indexer/indexer /usr/local/bin
CMD
["indexer", "
all
", "--config", "/app/indexer/indexer.toml"]
CMD
["indexer", "
index
", "--config", "/app/indexer/indexer.toml"]
indexer/cmd/indexer/cli.go
View file @
e422c544
package
main
package
main
import
(
import
(
"sync"
"github.com/ethereum-optimism/optimism/indexer"
"github.com/ethereum-optimism/optimism/indexer"
"github.com/ethereum-optimism/optimism/indexer/api"
"github.com/ethereum-optimism/optimism/indexer/api"
"github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/indexer/config"
...
@@ -66,35 +64,6 @@ func runApi(ctx *cli.Context) error {
...
@@ -66,35 +64,6 @@ func runApi(ctx *cli.Context) error {
return
api
.
Start
(
ctx
.
Context
)
return
api
.
Start
(
ctx
.
Context
)
}
}
func
runAll
(
ctx
*
cli
.
Context
)
error
{
log
:=
log
.
NewLogger
(
log
.
ReadCLIConfig
(
ctx
))
// Ensure both processes complete before returning.
var
wg
sync
.
WaitGroup
wg
.
Add
(
2
)
go
func
()
{
defer
wg
.
Done
()
err
:=
runApi
(
ctx
)
if
err
!=
nil
{
log
.
Error
(
"api process non-zero exit"
,
"err"
,
err
)
}
}()
go
func
()
{
defer
wg
.
Done
()
err
:=
runIndexer
(
ctx
)
if
err
!=
nil
{
log
.
Error
(
"indexer process non-zero exit"
,
"err"
,
err
)
}
}()
// We purposefully return no error since the indexer and api
// have no inter-dependencies. We simply rely on the logs to
// report a non-zero exit for either process.
wg
.
Wait
()
return
nil
}
func
newCli
(
GitCommit
string
,
GitDate
string
)
*
cli
.
App
{
func
newCli
(
GitCommit
string
,
GitDate
string
)
*
cli
.
App
{
flags
:=
[]
cli
.
Flag
{
ConfigFlag
}
flags
:=
[]
cli
.
Flag
{
ConfigFlag
}
flags
=
append
(
flags
,
log
.
CLIFlags
(
"INDEXER"
)
...
)
flags
=
append
(
flags
,
log
.
CLIFlags
(
"INDEXER"
)
...
)
...
@@ -115,12 +84,6 @@ func newCli(GitCommit string, GitDate string) *cli.App {
...
@@ -115,12 +84,6 @@ func newCli(GitCommit string, GitDate string) *cli.App {
Description
:
"Runs the indexing service"
,
Description
:
"Runs the indexing service"
,
Action
:
runIndexer
,
Action
:
runIndexer
,
},
},
{
Name
:
"all"
,
Flags
:
flags
,
Description
:
"Runs both the api service and the indexing service"
,
Action
:
runAll
,
},
{
{
Name
:
"version"
,
Name
:
"version"
,
Description
:
"print version"
,
Description
:
"print version"
,
...
...
indexer/config/config.go
View file @
e422c544
...
@@ -157,18 +157,20 @@ func LoadConfig(log log.Logger, path string) (Config, error) {
...
@@ -157,18 +157,20 @@ func LoadConfig(log log.Logger, path string) (Config, error) {
return
conf
,
err
return
conf
,
err
}
}
if
conf
.
Chain
.
Preset
!=
0
{
if
conf
.
Chain
.
Preset
==
DEVNET_L2_CHAIN_ID
{
preset
,
err
:=
GetDevnetPreset
()
if
err
!=
nil
{
return
conf
,
err
}
conf
.
Chain
=
preset
.
ChainConfig
}
else
if
conf
.
Chain
.
Preset
!=
0
{
preset
,
ok
:=
Presets
[
conf
.
Chain
.
Preset
]
preset
,
ok
:=
Presets
[
conf
.
Chain
.
Preset
]
if
!
ok
{
if
!
ok
{
return
conf
,
fmt
.
Errorf
(
"unknown preset: %d"
,
conf
.
Chain
.
Preset
)
return
conf
,
fmt
.
Errorf
(
"unknown preset: %d"
,
conf
.
Chain
.
Preset
)
}
}
log
.
Info
(
"detected preset"
,
"preset"
,
conf
.
Chain
.
Preset
,
"name"
,
preset
.
Name
)
log
.
Info
(
"detected preset"
,
"preset"
,
conf
.
Chain
.
Preset
,
"name"
,
preset
.
Name
)
log
.
Info
(
"setting L1 information from preset"
)
log
.
Info
(
"setting L1 information from preset"
)
conf
.
Chain
.
L1Contracts
=
preset
.
ChainConfig
.
L1Contracts
conf
.
Chain
=
preset
.
ChainConfig
conf
.
Chain
.
L1StartingHeight
=
preset
.
ChainConfig
.
L1StartingHeight
conf
.
Chain
.
L1BedrockStartingHeight
=
preset
.
ChainConfig
.
L1BedrockStartingHeight
conf
.
Chain
.
L2BedrockStartingHeight
=
preset
.
ChainConfig
.
L1BedrockStartingHeight
}
}
// Setup L2Contracts from predeploys
// Setup L2Contracts from predeploys
...
...
indexer/config/devnet.go
0 → 100644
View file @
e422c544
package
config
import
(
"encoding/json"
"errors"
"io/fs"
"os"
)
var
(
filePath
=
"../.devnet/addresses.json"
DEVNET_L2_CHAIN_ID
=
901
)
func
GetDevnetPreset
()
(
*
Preset
,
error
)
{
if
_
,
err
:=
os
.
Stat
(
filePath
);
errors
.
Is
(
err
,
fs
.
ErrNotExist
)
{
return
nil
,
err
}
content
,
err
:=
os
.
ReadFile
(
filePath
)
if
err
!=
nil
{
return
nil
,
err
}
var
l1Contracts
L1Contracts
if
err
:=
json
.
Unmarshal
(
content
,
&
l1Contracts
);
err
!=
nil
{
return
nil
,
err
}
if
err
!=
nil
{
return
nil
,
err
}
return
&
Preset
{
Name
:
"devnet"
,
ChainConfig
:
ChainConfig
{
Preset
:
DEVNET_L2_CHAIN_ID
,
L1Contracts
:
l1Contracts
,
},
},
nil
}
indexer/config/presets.go
View file @
e422c544
...
@@ -16,6 +16,7 @@ var Presets = map[int]Preset{
...
@@ -16,6 +16,7 @@ var Presets = map[int]Preset{
10
:
{
10
:
{
Name
:
"Optimism"
,
Name
:
"Optimism"
,
ChainConfig
:
ChainConfig
{
ChainConfig
:
ChainConfig
{
Preset
:
10
,
L1Contracts
:
L1Contracts
{
L1Contracts
:
L1Contracts
{
AddressManager
:
common
.
HexToAddress
(
"0xdE1FCfB0851916CA5101820A69b13a4E276bd81F"
),
AddressManager
:
common
.
HexToAddress
(
"0xdE1FCfB0851916CA5101820A69b13a4E276bd81F"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0x229047fed2591dbec1eF1118d64F7aF3dB9EB290"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0x229047fed2591dbec1eF1118d64F7aF3dB9EB290"
),
...
@@ -37,6 +38,7 @@ var Presets = map[int]Preset{
...
@@ -37,6 +38,7 @@ var Presets = map[int]Preset{
420
:
{
420
:
{
Name
:
"Optimism Goerli"
,
Name
:
"Optimism Goerli"
,
ChainConfig
:
ChainConfig
{
ChainConfig
:
ChainConfig
{
Preset
:
420
,
L1Contracts
:
L1Contracts
{
L1Contracts
:
L1Contracts
{
AddressManager
:
common
.
HexToAddress
(
"0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
),
AddressManager
:
common
.
HexToAddress
(
"0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60"
),
...
@@ -58,6 +60,7 @@ var Presets = map[int]Preset{
...
@@ -58,6 +60,7 @@ var Presets = map[int]Preset{
8453
:
{
8453
:
{
Name
:
"Base"
,
Name
:
"Base"
,
ChainConfig
:
ChainConfig
{
ChainConfig
:
ChainConfig
{
Preset
:
8453
,
L1Contracts
:
L1Contracts
{
L1Contracts
:
L1Contracts
{
AddressManager
:
common
.
HexToAddress
(
"0x8EfB6B5c4767B09Dc9AA6Af4eAA89F749522BaE2"
),
AddressManager
:
common
.
HexToAddress
(
"0x8EfB6B5c4767B09Dc9AA6Af4eAA89F749522BaE2"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0x73a79Fab69143498Ed3712e519A88a918e1f4072"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0x73a79Fab69143498Ed3712e519A88a918e1f4072"
),
...
@@ -73,6 +76,7 @@ var Presets = map[int]Preset{
...
@@ -73,6 +76,7 @@ var Presets = map[int]Preset{
84531
:
{
84531
:
{
Name
:
"Base Goerli"
,
Name
:
"Base Goerli"
,
ChainConfig
:
ChainConfig
{
ChainConfig
:
ChainConfig
{
Preset
:
84531
,
L1Contracts
:
L1Contracts
{
L1Contracts
:
L1Contracts
{
AddressManager
:
common
.
HexToAddress
(
"0x4Cf6b56b14c6CFcB72A75611080514F94624c54e"
),
AddressManager
:
common
.
HexToAddress
(
"0x4Cf6b56b14c6CFcB72A75611080514F94624c54e"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xb15eea247eCE011C68a614e4a77AD648ff495bc1"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xb15eea247eCE011C68a614e4a77AD648ff495bc1"
),
...
@@ -88,6 +92,7 @@ var Presets = map[int]Preset{
...
@@ -88,6 +92,7 @@ var Presets = map[int]Preset{
7777777
:
{
7777777
:
{
Name
:
"Zora"
,
Name
:
"Zora"
,
ChainConfig
:
ChainConfig
{
ChainConfig
:
ChainConfig
{
Preset
:
7777777
,
L1Contracts
:
L1Contracts
{
L1Contracts
:
L1Contracts
{
AddressManager
:
common
.
HexToAddress
(
"0xEF8115F2733fb2033a7c756402Fc1deaa56550Ef"
),
AddressManager
:
common
.
HexToAddress
(
"0xEF8115F2733fb2033a7c756402Fc1deaa56550Ef"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xA3cAB0126d5F504B071b81a3e8A2BBBF17930d86"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xA3cAB0126d5F504B071b81a3e8A2BBBF17930d86"
),
...
@@ -103,6 +108,7 @@ var Presets = map[int]Preset{
...
@@ -103,6 +108,7 @@ var Presets = map[int]Preset{
999
:
{
999
:
{
Name
:
"Zora Goerli"
,
Name
:
"Zora Goerli"
,
ChainConfig
:
ChainConfig
{
ChainConfig
:
ChainConfig
{
Preset
:
999
,
L1Contracts
:
L1Contracts
{
L1Contracts
:
L1Contracts
{
AddressManager
:
common
.
HexToAddress
(
"0x54f4676203dEDA6C08E0D40557A119c602bFA246"
),
AddressManager
:
common
.
HexToAddress
(
"0x54f4676203dEDA6C08E0D40557A119c602bFA246"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xF66C9A5E4fE1A8a9bc44a4aF80505a4C3620Ee64"
),
SystemConfigProxy
:
common
.
HexToAddress
(
"0xF66C9A5E4fE1A8a9bc44a4aF80505a4C3620Ee64"
),
...
...
op-challenger/game/fault/agent.go
View file @
e422c544
...
@@ -30,6 +30,7 @@ type ClaimLoader interface {
...
@@ -30,6 +30,7 @@ type ClaimLoader interface {
type
Agent
struct
{
type
Agent
struct
{
metrics
metrics
.
Metricer
metrics
metrics
.
Metricer
fdgAddr
common
.
Address
solver
*
solver
.
GameSolver
solver
*
solver
.
GameSolver
loader
ClaimLoader
loader
ClaimLoader
responder
Responder
responder
Responder
...
@@ -39,9 +40,10 @@ type Agent struct {
...
@@ -39,9 +40,10 @@ type Agent struct {
log
log
.
Logger
log
log
.
Logger
}
}
func
NewAgent
(
m
metrics
.
Metricer
,
loader
ClaimLoader
,
maxDepth
int
,
trace
types
.
TraceProvider
,
responder
Responder
,
updater
types
.
OracleUpdater
,
agreeWithProposedOutput
bool
,
log
log
.
Logger
)
*
Agent
{
func
NewAgent
(
m
metrics
.
Metricer
,
addr
common
.
Address
,
loader
ClaimLoader
,
maxDepth
int
,
trace
types
.
TraceProvider
,
responder
Responder
,
updater
types
.
OracleUpdater
,
agreeWithProposedOutput
bool
,
log
log
.
Logger
)
*
Agent
{
return
&
Agent
{
return
&
Agent
{
metrics
:
m
,
metrics
:
m
,
fdgAddr
:
addr
,
solver
:
solver
.
NewGameSolver
(
maxDepth
,
trace
),
solver
:
solver
.
NewGameSolver
(
maxDepth
,
trace
),
loader
:
loader
,
loader
:
loader
,
responder
:
responder
,
responder
:
responder
,
...
@@ -196,6 +198,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (types.Game, error) {
...
@@ -196,6 +198,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (types.Game, error) {
if
len
(
claims
)
==
0
{
if
len
(
claims
)
==
0
{
return
nil
,
errors
.
New
(
"no claims"
)
return
nil
,
errors
.
New
(
"no claims"
)
}
}
a
.
metrics
.
RecordGameClaimCount
(
a
.
fdgAddr
.
String
(),
len
(
claims
))
game
:=
types
.
NewGameState
(
a
.
agreeWithProposedOutput
,
claims
[
0
],
uint64
(
a
.
maxDepth
))
game
:=
types
.
NewGameState
(
a
.
agreeWithProposedOutput
,
claims
[
0
],
uint64
(
a
.
maxDepth
))
if
err
:=
game
.
PutAll
(
claims
[
1
:
]);
err
!=
nil
{
if
err
:=
game
.
PutAll
(
claims
[
1
:
]);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load claims into the local state: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to load claims into the local state: %w"
,
err
)
...
...
op-challenger/game/fault/agent_test.go
View file @
e422c544
...
@@ -10,10 +10,11 @@ import (
...
@@ -10,10 +10,11 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)
)
// TestShouldResolve tests the resolution logic.
// TestShouldResolve tests the resolution logic.
...
@@ -110,11 +111,12 @@ func TestLoadClaimsWhenGameNotResolvable(t *testing.T) {
...
@@ -110,11 +111,12 @@ func TestLoadClaimsWhenGameNotResolvable(t *testing.T) {
func
setupTestAgent
(
t
*
testing
.
T
,
agreeWithProposedOutput
bool
)
(
*
Agent
,
*
stubClaimLoader
,
*
stubResponder
)
{
func
setupTestAgent
(
t
*
testing
.
T
,
agreeWithProposedOutput
bool
)
(
*
Agent
,
*
stubClaimLoader
,
*
stubResponder
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlInfo
)
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlInfo
)
claimLoader
:=
&
stubClaimLoader
{}
claimLoader
:=
&
stubClaimLoader
{}
addr
:=
common
.
HexToAddress
(
"0x1234"
)
depth
:=
4
depth
:=
4
trace
:=
alphabet
.
NewTraceProvider
(
"abcd"
,
uint64
(
depth
))
trace
:=
alphabet
.
NewTraceProvider
(
"abcd"
,
uint64
(
depth
))
responder
:=
&
stubResponder
{}
responder
:=
&
stubResponder
{}
updater
:=
&
stubUpdater
{}
updater
:=
&
stubUpdater
{}
agent
:=
NewAgent
(
metrics
.
NoopMetrics
,
claimLoader
,
depth
,
trace
,
responder
,
updater
,
agreeWithProposedOutput
,
logger
)
agent
:=
NewAgent
(
metrics
.
NoopMetrics
,
addr
,
claimLoader
,
depth
,
trace
,
responder
,
updater
,
agreeWithProposedOutput
,
logger
)
return
agent
,
claimLoader
,
responder
return
agent
,
claimLoader
,
responder
}
}
...
...
op-challenger/game/fault/player.go
View file @
e422c544
...
@@ -106,7 +106,7 @@ func NewGamePlayer(
...
@@ -106,7 +106,7 @@ func NewGamePlayer(
}
}
return
&
GamePlayer
{
return
&
GamePlayer
{
act
:
NewAgent
(
m
,
loader
,
int
(
gameDepth
),
provider
,
responder
,
updater
,
cfg
.
AgreeWithProposedOutput
,
logger
)
.
Act
,
act
:
NewAgent
(
m
,
addr
,
loader
,
int
(
gameDepth
),
provider
,
responder
,
updater
,
cfg
.
AgreeWithProposedOutput
,
logger
)
.
Act
,
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
loader
:
loader
,
loader
:
loader
,
logger
:
logger
,
logger
:
logger
,
...
@@ -114,6 +114,10 @@ func NewGamePlayer(
...
@@ -114,6 +114,10 @@ func NewGamePlayer(
},
nil
},
nil
}
}
func
(
g
*
GamePlayer
)
Status
()
gameTypes
.
GameStatus
{
return
g
.
status
}
func
(
g
*
GamePlayer
)
ProgressGame
(
ctx
context
.
Context
)
gameTypes
.
GameStatus
{
func
(
g
*
GamePlayer
)
ProgressGame
(
ctx
context
.
Context
)
gameTypes
.
GameStatus
{
if
g
.
status
!=
gameTypes
.
GameStatusInProgress
{
if
g
.
status
!=
gameTypes
.
GameStatusInProgress
{
// Game is already complete so don't try to perform further actions.
// Game is already complete so don't try to perform further actions.
...
...
op-challenger/game/scheduler/coordinator.go
View file @
e422c544
...
@@ -109,9 +109,14 @@ func (c *coordinator) createJob(game common.Address) (*job, error) {
...
@@ -109,9 +109,14 @@ func (c *coordinator) createJob(game common.Address) (*job, error) {
return
nil
,
fmt
.
Errorf
(
"failed to create game player: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to create game player: %w"
,
err
)
}
}
state
.
player
=
player
state
.
player
=
player
state
.
status
=
player
.
Status
()
}
}
state
.
inflight
=
true
state
.
inflight
=
true
return
&
job
{
addr
:
game
,
player
:
state
.
player
},
nil
if
state
.
status
!=
types
.
GameStatusInProgress
{
c
.
logger
.
Debug
(
"Not rescheduling resolved game"
,
"game"
,
game
,
"status"
,
state
.
status
)
return
nil
,
nil
}
return
&
job
{
addr
:
game
,
player
:
state
.
player
,
status
:
state
.
status
},
nil
}
}
func
(
c
*
coordinator
)
enqueueJob
(
ctx
context
.
Context
,
j
job
)
error
{
func
(
c
*
coordinator
)
enqueueJob
(
ctx
context
.
Context
,
j
job
)
error
{
...
...
op-challenger/game/scheduler/coordinator_test.go
View file @
e422c544
...
@@ -150,7 +150,10 @@ func TestDeleteDataForResolvedGames(t *testing.T) {
...
@@ -150,7 +150,10 @@ func TestDeleteDataForResolvedGames(t *testing.T) {
gameAddrs
:=
[]
common
.
Address
{
gameAddr1
,
gameAddr2
,
gameAddr3
}
gameAddrs
:=
[]
common
.
Address
{
gameAddr1
,
gameAddr2
,
gameAddr3
}
require
.
NoError
(
t
,
c
.
schedule
(
ctx
,
gameAddrs
))
require
.
NoError
(
t
,
c
.
schedule
(
ctx
,
gameAddrs
))
require
.
Len
(
t
,
workQueue
,
len
(
gameAddrs
),
"should schedule all games"
)
// The work queue should only contain jobs for games 1 and 2
// A resolved game should not be scheduled for an update.
// This makes the inflight game metric more robust.
require
.
Len
(
t
,
workQueue
,
2
,
"should schedule all games"
)
// Game 1 progresses and is still in progress
// Game 1 progresses and is still in progress
// Game 2 progresses and is now resolved
// Game 2 progresses and is now resolved
...
@@ -249,6 +252,10 @@ func (g *stubGame) ProgressGame(_ context.Context) types.GameStatus {
...
@@ -249,6 +252,10 @@ func (g *stubGame) ProgressGame(_ context.Context) types.GameStatus {
return
g
.
status
return
g
.
status
}
}
func
(
g
*
stubGame
)
Status
()
types
.
GameStatus
{
return
g
.
status
}
type
createdGames
struct
{
type
createdGames
struct
{
t
*
testing
.
T
t
*
testing
.
T
createCompleted
common
.
Address
createCompleted
common
.
Address
...
...
op-challenger/game/scheduler/scheduler.go
View file @
e422c544
...
@@ -15,11 +15,16 @@ type SchedulerMetricer interface {
...
@@ -15,11 +15,16 @@ type SchedulerMetricer interface {
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
RecordGameUpdateScheduled
()
RecordGameUpdateScheduled
()
RecordGameUpdateCompleted
()
RecordGameUpdateCompleted
()
IncActiveExecutors
()
DecActiveExecutors
()
IncIdleExecutors
()
DecIdleExecutors
()
}
}
type
Scheduler
struct
{
type
Scheduler
struct
{
logger
log
.
Logger
logger
log
.
Logger
coordinator
*
coordinator
coordinator
*
coordinator
m
SchedulerMetricer
maxConcurrency
uint
maxConcurrency
uint
scheduleQueue
chan
[]
common
.
Address
scheduleQueue
chan
[]
common
.
Address
jobQueue
chan
job
jobQueue
chan
job
...
@@ -40,6 +45,7 @@ func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxC
...
@@ -40,6 +45,7 @@ func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxC
return
&
Scheduler
{
return
&
Scheduler
{
logger
:
logger
,
logger
:
logger
,
m
:
m
,
coordinator
:
newCoordinator
(
logger
,
m
,
jobQueue
,
resultQueue
,
createPlayer
,
disk
),
coordinator
:
newCoordinator
(
logger
,
m
,
jobQueue
,
resultQueue
,
createPlayer
,
disk
),
maxConcurrency
:
maxConcurrency
,
maxConcurrency
:
maxConcurrency
,
scheduleQueue
:
scheduleQueue
,
scheduleQueue
:
scheduleQueue
,
...
@@ -48,13 +54,24 @@ func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxC
...
@@ -48,13 +54,24 @@ func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxC
}
}
}
}
func
(
s
*
Scheduler
)
ThreadActive
()
{
s
.
m
.
IncActiveExecutors
()
s
.
m
.
DecIdleExecutors
()
}
func
(
s
*
Scheduler
)
ThreadIdle
()
{
s
.
m
.
IncIdleExecutors
()
s
.
m
.
DecActiveExecutors
()
}
func
(
s
*
Scheduler
)
Start
(
ctx
context
.
Context
)
{
func
(
s
*
Scheduler
)
Start
(
ctx
context
.
Context
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
s
.
cancel
=
cancel
s
.
cancel
=
cancel
for
i
:=
uint
(
0
);
i
<
s
.
maxConcurrency
;
i
++
{
for
i
:=
uint
(
0
);
i
<
s
.
maxConcurrency
;
i
++
{
s
.
m
.
IncIdleExecutors
()
s
.
wg
.
Add
(
1
)
s
.
wg
.
Add
(
1
)
go
progressGames
(
ctx
,
s
.
jobQueue
,
s
.
resultQueue
,
&
s
.
wg
)
go
progressGames
(
ctx
,
s
.
jobQueue
,
s
.
resultQueue
,
&
s
.
wg
,
s
.
ThreadActive
,
s
.
ThreadIdle
)
}
}
s
.
wg
.
Add
(
1
)
s
.
wg
.
Add
(
1
)
...
...
op-challenger/game/scheduler/types.go
View file @
e422c544
...
@@ -10,6 +10,7 @@ import (
...
@@ -10,6 +10,7 @@ import (
type
GamePlayer
interface
{
type
GamePlayer
interface
{
ProgressGame
(
ctx
context
.
Context
)
types
.
GameStatus
ProgressGame
(
ctx
context
.
Context
)
types
.
GameStatus
Status
()
types
.
GameStatus
}
}
type
DiskManager
interface
{
type
DiskManager
interface
{
...
...
op-challenger/game/scheduler/worker.go
View file @
e422c544
...
@@ -8,15 +8,17 @@ import (
...
@@ -8,15 +8,17 @@ import (
// progressGames accepts jobs from in channel, calls ProgressGame on the job.player and returns the job
// progressGames accepts jobs from in channel, calls ProgressGame on the job.player and returns the job
// with updated job.resolved via the out channel.
// with updated job.resolved via the out channel.
// The loop exits when the ctx is done. wg.Done() is called when the function returns.
// The loop exits when the ctx is done. wg.Done() is called when the function returns.
func
progressGames
(
ctx
context
.
Context
,
in
<-
chan
job
,
out
chan
<-
job
,
wg
*
sync
.
WaitGroup
)
{
func
progressGames
(
ctx
context
.
Context
,
in
<-
chan
job
,
out
chan
<-
job
,
wg
*
sync
.
WaitGroup
,
threadActive
,
threadIdle
func
()
)
{
defer
wg
.
Done
()
defer
wg
.
Done
()
for
{
for
{
select
{
select
{
case
<-
ctx
.
Done
()
:
case
<-
ctx
.
Done
()
:
return
return
case
j
:=
<-
in
:
case
j
:=
<-
in
:
threadActive
()
j
.
status
=
j
.
player
.
ProgressGame
(
ctx
)
j
.
status
=
j
.
player
.
ProgressGame
(
ctx
)
out
<-
j
out
<-
j
threadIdle
()
}
}
}
}
}
}
op-challenger/game/scheduler/worker_test.go
View file @
e422c544
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
"time"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
)
)
...
@@ -15,18 +16,32 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
...
@@ -15,18 +16,32 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
in
:=
make
(
chan
job
,
2
)
in
:=
make
(
chan
job
,
2
)
out
:=
make
(
chan
job
,
2
)
out
:=
make
(
chan
job
,
2
)
ms
:=
&
metricSink
{}
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
defer
cancel
()
var
wg
sync
.
WaitGroup
var
wg
sync
.
WaitGroup
wg
.
Add
(
1
)
wg
.
Add
(
1
)
go
progressGames
(
ctx
,
in
,
out
,
&
wg
)
go
progressGames
(
ctx
,
in
,
out
,
&
wg
,
ms
.
ThreadActive
,
ms
.
ThreadIdle
)
in
<-
job
{
in
<-
job
{
player
:
&
stubPlayer
{
status
:
types
.
GameStatusInProgress
},
player
:
&
stubPlayer
{
status
:
types
.
GameStatusInProgress
},
}
}
waitErr
:=
wait
.
For
(
context
.
Background
(),
100
*
time
.
Millisecond
,
func
()
(
bool
,
error
)
{
return
ms
.
activeCalls
>=
1
,
nil
})
require
.
NoError
(
t
,
waitErr
)
require
.
Equal
(
t
,
ms
.
activeCalls
,
1
)
require
.
Equal
(
t
,
ms
.
idleCalls
,
1
)
in
<-
job
{
in
<-
job
{
player
:
&
stubPlayer
{
status
:
types
.
GameStatusDefenderWon
},
player
:
&
stubPlayer
{
status
:
types
.
GameStatusDefenderWon
},
}
}
waitErr
=
wait
.
For
(
context
.
Background
(),
100
*
time
.
Millisecond
,
func
()
(
bool
,
error
)
{
return
ms
.
activeCalls
>=
2
,
nil
})
require
.
NoError
(
t
,
waitErr
)
require
.
Equal
(
t
,
ms
.
activeCalls
,
2
)
require
.
Equal
(
t
,
ms
.
idleCalls
,
2
)
result1
:=
readWithTimeout
(
t
,
out
)
result1
:=
readWithTimeout
(
t
,
out
)
result2
:=
readWithTimeout
(
t
,
out
)
result2
:=
readWithTimeout
(
t
,
out
)
...
@@ -39,6 +54,19 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
...
@@ -39,6 +54,19 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
wg
.
Wait
()
wg
.
Wait
()
}
}
type
metricSink
struct
{
activeCalls
int
idleCalls
int
}
func
(
m
*
metricSink
)
ThreadActive
()
{
m
.
activeCalls
++
}
func
(
m
*
metricSink
)
ThreadIdle
()
{
m
.
idleCalls
++
}
type
stubPlayer
struct
{
type
stubPlayer
struct
{
status
types
.
GameStatus
status
types
.
GameStatus
}
}
...
@@ -47,6 +75,10 @@ func (s *stubPlayer) ProgressGame(ctx context.Context) types.GameStatus {
...
@@ -47,6 +75,10 @@ func (s *stubPlayer) ProgressGame(ctx context.Context) types.GameStatus {
return
s
.
status
return
s
.
status
}
}
func
(
s
*
stubPlayer
)
Status
()
types
.
GameStatus
{
return
s
.
status
}
func
readWithTimeout
[
T
any
](
t
*
testing
.
T
,
ch
<-
chan
T
)
T
{
func
readWithTimeout
[
T
any
](
t
*
testing
.
T
,
ch
<-
chan
T
)
T
{
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
10
*
time
.
Second
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
10
*
time
.
Second
)
defer
cancel
()
defer
cancel
()
...
...
op-challenger/metrics/metrics.go
View file @
e422c544
...
@@ -25,10 +25,17 @@ type Metricer interface {
...
@@ -25,10 +25,17 @@ type Metricer interface {
RecordGameMove
()
RecordGameMove
()
RecordCannonExecutionTime
(
t
float64
)
RecordCannonExecutionTime
(
t
float64
)
RecordGameClaimCount
(
addr
string
,
count
int
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
RecordGameUpdateScheduled
()
RecordGameUpdateScheduled
()
RecordGameUpdateCompleted
()
RecordGameUpdateCompleted
()
IncActiveExecutors
()
DecActiveExecutors
()
IncIdleExecutors
()
DecIdleExecutors
()
}
}
type
Metrics
struct
{
type
Metrics
struct
{
...
@@ -41,11 +48,15 @@ type Metrics struct {
...
@@ -41,11 +48,15 @@ type Metrics struct {
info
prometheus
.
GaugeVec
info
prometheus
.
GaugeVec
up
prometheus
.
Gauge
up
prometheus
.
Gauge
executors
prometheus
.
GaugeVec
moves
prometheus
.
Counter
moves
prometheus
.
Counter
steps
prometheus
.
Counter
steps
prometheus
.
Counter
cannonExecutionTime
prometheus
.
Histogram
cannonExecutionTime
prometheus
.
Histogram
gameClaimCount
prometheus
.
GaugeVec
trackedGames
prometheus
.
GaugeVec
trackedGames
prometheus
.
GaugeVec
inflightGames
prometheus
.
Gauge
inflightGames
prometheus
.
Gauge
}
}
...
@@ -75,6 +86,13 @@ func NewMetrics() *Metrics {
...
@@ -75,6 +86,13 @@ func NewMetrics() *Metrics {
Name
:
"up"
,
Name
:
"up"
,
Help
:
"1 if the op-challenger has finished starting up"
,
Help
:
"1 if the op-challenger has finished starting up"
,
}),
}),
executors
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
Namespace
,
Name
:
"executors"
,
Help
:
"Number of active and idle executors"
,
},
[]
string
{
"status"
,
}),
moves
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
moves
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
Namespace
,
Namespace
:
Namespace
,
Name
:
"moves"
,
Name
:
"moves"
,
...
@@ -93,6 +111,13 @@ func NewMetrics() *Metrics {
...
@@ -93,6 +111,13 @@ func NewMetrics() *Metrics {
[]
float64
{
1.0
,
10.0
},
[]
float64
{
1.0
,
10.0
},
prometheus
.
ExponentialBuckets
(
30.0
,
2.0
,
14
)
...
),
prometheus
.
ExponentialBuckets
(
30.0
,
2.0
,
14
)
...
),
}),
}),
gameClaimCount
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
Namespace
,
Name
:
"game_claim_count"
,
Help
:
"Number of claims in the game"
,
},
[]
string
{
"game_address"
,
}),
trackedGames
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
trackedGames
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
Namespace
,
Namespace
:
Namespace
,
Name
:
"tracked_games"
,
Name
:
"tracked_games"
,
...
@@ -149,6 +174,26 @@ func (m *Metrics) RecordCannonExecutionTime(t float64) {
...
@@ -149,6 +174,26 @@ func (m *Metrics) RecordCannonExecutionTime(t float64) {
m
.
cannonExecutionTime
.
Observe
(
t
)
m
.
cannonExecutionTime
.
Observe
(
t
)
}
}
func
(
m
*
Metrics
)
IncActiveExecutors
()
{
m
.
executors
.
WithLabelValues
(
"active"
)
.
Inc
()
}
func
(
m
*
Metrics
)
DecActiveExecutors
()
{
m
.
executors
.
WithLabelValues
(
"active"
)
.
Dec
()
}
func
(
m
*
Metrics
)
IncIdleExecutors
()
{
m
.
executors
.
WithLabelValues
(
"idle"
)
.
Inc
()
}
func
(
m
*
Metrics
)
DecIdleExecutors
()
{
m
.
executors
.
WithLabelValues
(
"idle"
)
.
Dec
()
}
func
(
m
*
Metrics
)
RecordGameClaimCount
(
addr
string
,
count
int
)
{
m
.
gameClaimCount
.
With
(
prometheus
.
Labels
{
"game_address"
:
addr
})
.
Set
(
float64
(
count
))
}
func
(
m
*
Metrics
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
{
func
(
m
*
Metrics
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
{
m
.
trackedGames
.
WithLabelValues
(
"in_progress"
)
.
Set
(
float64
(
inProgress
))
m
.
trackedGames
.
WithLabelValues
(
"in_progress"
)
.
Set
(
float64
(
inProgress
))
m
.
trackedGames
.
WithLabelValues
(
"defender_won"
)
.
Set
(
float64
(
defenderWon
))
m
.
trackedGames
.
WithLabelValues
(
"defender_won"
)
.
Set
(
float64
(
defenderWon
))
...
...
op-challenger/metrics/noop.go
View file @
e422c544
...
@@ -22,3 +22,10 @@ func (*NoopMetricsImpl) RecordGamesStatus(inProgress, defenderWon, challengerWon
...
@@ -22,3 +22,10 @@ func (*NoopMetricsImpl) RecordGamesStatus(inProgress, defenderWon, challengerWon
func
(
*
NoopMetricsImpl
)
RecordGameUpdateScheduled
()
{}
func
(
*
NoopMetricsImpl
)
RecordGameUpdateScheduled
()
{}
func
(
*
NoopMetricsImpl
)
RecordGameUpdateCompleted
()
{}
func
(
*
NoopMetricsImpl
)
RecordGameUpdateCompleted
()
{}
func
(
*
NoopMetricsImpl
)
IncActiveExecutors
()
{}
func
(
*
NoopMetricsImpl
)
DecActiveExecutors
()
{}
func
(
*
NoopMetricsImpl
)
IncIdleExecutors
()
{}
func
(
*
NoopMetricsImpl
)
DecIdleExecutors
()
{}
func
(
*
NoopMetricsImpl
)
RecordGameClaimCount
(
addr
string
,
count
int
)
{}
ops/check-changed/main.py
View file @
e422c544
...
@@ -56,11 +56,7 @@ log = logging.getLogger(__name__)
...
@@ -56,11 +56,7 @@ log = logging.getLogger(__name__)
def
main
():
def
main
():
patterns
=
sys
.
argv
[
1
]
.
split
(
','
)
patterns
=
sys
.
argv
[
1
]
.
split
(
','
)
patterns
=
patterns
+
REBUILD_ALL_PATTERNS
# temporarily only run indexer tests if indexer is changed because the tests are flaky
if
len
(
patterns
)
!=
1
or
patterns
[
0
]
!=
"indexer"
:
patterns
=
patterns
+
REBUILD_ALL_PATTERNS
fp
=
os
.
path
.
realpath
(
__file__
)
fp
=
os
.
path
.
realpath
(
__file__
)
monorepo_path
=
os
.
path
.
realpath
(
os
.
path
.
join
(
fp
,
'..'
,
'..'
))
monorepo_path
=
os
.
path
.
realpath
(
os
.
path
.
join
(
fp
,
'..'
,
'..'
))
...
...
pnpm-lock.yaml
View file @
e422c544
...
@@ -184,7 +184,7 @@ importers:
...
@@ -184,7 +184,7 @@ importers:
version
:
2.17.2(ts-node@10.9.1)(typescript@5.2.2)
version
:
2.17.2(ts-node@10.9.1)(typescript@5.2.2)
ts-node
:
ts-node
:
specifier
:
^10.9.1
specifier
:
^10.9.1
version
:
10.9.1(@types/node@20.6.
2
)(typescript@5.2.2)
version
:
10.9.1(@types/node@20.6.
3
)(typescript@5.2.2)
tsx
:
tsx
:
specifier
:
^3.12.7
specifier
:
^3.12.7
version
:
3.12.7
version
:
3.12.7
...
@@ -3711,20 +3711,20 @@ packages:
...
@@ -3711,20 +3711,20 @@ packages:
/@types/bn.js@4.11.6
:
/@types/bn.js@4.11.6
:
resolution
:
{
integrity
:
sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==
}
resolution
:
{
integrity
:
sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/bn.js@5.1.0
:
/@types/bn.js@5.1.0
:
resolution
:
{
integrity
:
sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==
}
resolution
:
{
integrity
:
sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/body-parser@1.19.1
:
/@types/body-parser@1.19.1
:
resolution
:
{
integrity
:
sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==
}
resolution
:
{
integrity
:
sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==
}
dependencies
:
dependencies
:
'
@types/connect'
:
3.4.35
'
@types/connect'
:
3.4.35
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/chai-as-promised@7.1.5
:
/@types/chai-as-promised@7.1.5
:
...
@@ -3750,7 +3750,7 @@ packages:
...
@@ -3750,7 +3750,7 @@ packages:
/@types/connect@3.4.35
:
/@types/connect@3.4.35
:
resolution
:
{
integrity
:
sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
}
resolution
:
{
integrity
:
sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
/@types/dateformat@5.0.0
:
/@types/dateformat@5.0.0
:
resolution
:
{
integrity
:
sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==
}
resolution
:
{
integrity
:
sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==
}
...
@@ -3764,7 +3764,7 @@ packages:
...
@@ -3764,7 +3764,7 @@ packages:
/@types/express-serve-static-core@4.17.35
:
/@types/express-serve-static-core@4.17.35
:
resolution
:
{
integrity
:
sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==
}
resolution
:
{
integrity
:
sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
'
@types/qs'
:
6.9.7
'
@types/qs'
:
6.9.7
'
@types/range-parser'
:
1.2.4
'
@types/range-parser'
:
1.2.4
'
@types/send'
:
0.17.1
'
@types/send'
:
0.17.1
...
@@ -3810,7 +3810,7 @@ packages:
...
@@ -3810,7 +3810,7 @@ packages:
dependencies
:
dependencies
:
'
@types/abstract-leveldown'
:
5.0.2
'
@types/abstract-leveldown'
:
5.0.2
'
@types/level-errors'
:
3.0.0
'
@types/level-errors'
:
3.0.0
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/lru-cache@5.1.1
:
/@types/lru-cache@5.1.1
:
...
@@ -3842,7 +3842,7 @@ packages:
...
@@ -3842,7 +3842,7 @@ packages:
/@types/mkdirp@0.5.2
:
/@types/mkdirp@0.5.2
:
resolution
:
{
integrity
:
sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==
}
resolution
:
{
integrity
:
sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/mocha@10.0.1
:
/@types/mocha@10.0.1
:
...
@@ -3861,7 +3861,7 @@ packages:
...
@@ -3861,7 +3861,7 @@ packages:
/@types/node-fetch@2.6.4
:
/@types/node-fetch@2.6.4
:
resolution
:
{
integrity
:
sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==
}
resolution
:
{
integrity
:
sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
form-data
:
3.0.1
form-data
:
3.0.1
dev
:
true
dev
:
true
...
@@ -3878,6 +3878,10 @@ packages:
...
@@ -3878,6 +3878,10 @@ packages:
/@types/node@20.6.2
:
/@types/node@20.6.2
:
resolution
:
{
integrity
:
sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
}
resolution
:
{
integrity
:
sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
}
dev
:
true
/@types/node@20.6.3
:
resolution
:
{
integrity
:
sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==
}
/@types/normalize-package-data@2.4.1
:
/@types/normalize-package-data@2.4.1
:
resolution
:
{
integrity
:
sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
}
resolution
:
{
integrity
:
sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
}
...
@@ -3889,7 +3893,7 @@ packages:
...
@@ -3889,7 +3893,7 @@ packages:
/@types/pbkdf2@3.1.0
:
/@types/pbkdf2@3.1.0
:
resolution
:
{
integrity
:
sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==
}
resolution
:
{
integrity
:
sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/pino-multi-stream@5.1.3
:
/@types/pino-multi-stream@5.1.3
:
...
@@ -3907,13 +3911,13 @@ packages:
...
@@ -3907,13 +3911,13 @@ packages:
/@types/pino-std-serializers@2.4.1
:
/@types/pino-std-serializers@2.4.1
:
resolution
:
{
integrity
:
sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==
}
resolution
:
{
integrity
:
sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/pino@6.3.11
:
/@types/pino@6.3.11
:
resolution
:
{
integrity
:
sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ==
}
resolution
:
{
integrity
:
sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
'
@types/pino-pretty'
:
4.7.1
'
@types/pino-pretty'
:
4.7.1
'
@types/pino-std-serializers'
:
2.4.1
'
@types/pino-std-serializers'
:
2.4.1
sonic-boom
:
2.8.0
sonic-boom
:
2.8.0
...
@@ -3959,7 +3963,7 @@ packages:
...
@@ -3959,7 +3963,7 @@ packages:
/@types/readable-stream@2.3.15
:
/@types/readable-stream@2.3.15
:
resolution
:
{
integrity
:
sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==
}
resolution
:
{
integrity
:
sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
safe-buffer
:
5.1.2
safe-buffer
:
5.1.2
dev
:
true
dev
:
true
...
@@ -3970,7 +3974,7 @@ packages:
...
@@ -3970,7 +3974,7 @@ packages:
/@types/secp256k1@4.0.3
:
/@types/secp256k1@4.0.3
:
resolution
:
{
integrity
:
sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==
}
resolution
:
{
integrity
:
sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/seedrandom@3.0.1
:
/@types/seedrandom@3.0.1
:
...
@@ -3989,14 +3993,14 @@ packages:
...
@@ -3989,14 +3993,14 @@ packages:
resolution
:
{
integrity
:
sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==
}
resolution
:
{
integrity
:
sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==
}
dependencies
:
dependencies
:
'
@types/mime'
:
1.3.2
'
@types/mime'
:
1.3.2
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/serve-static@1.13.10
:
/@types/serve-static@1.13.10
:
resolution
:
{
integrity
:
sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
}
resolution
:
{
integrity
:
sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
}
dependencies
:
dependencies
:
'
@types/mime'
:
1.3.2
'
@types/mime'
:
1.3.2
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@types/sinon-chai@3.2.5
:
/@types/sinon-chai@3.2.5
:
...
@@ -4033,18 +4037,18 @@ packages:
...
@@ -4033,18 +4037,18 @@ packages:
/@types/ws@7.4.7
:
/@types/ws@7.4.7
:
resolution
:
{
integrity
:
sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==
}
resolution
:
{
integrity
:
sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
/@types/ws@8.5.3
:
/@types/ws@8.5.3
:
resolution
:
{
integrity
:
sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
}
resolution
:
{
integrity
:
sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
false
dev
:
false
/@types/ws@8.5.5
:
/@types/ws@8.5.5
:
resolution
:
{
integrity
:
sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==
}
resolution
:
{
integrity
:
sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
dev
:
true
dev
:
true
/@typescript-eslint/eslint-plugin@6.7.0(@typescript-eslint/parser@6.4.0)(eslint@8.49.0)(typescript@5.1.6)
:
/@typescript-eslint/eslint-plugin@6.7.0(@typescript-eslint/parser@6.4.0)(eslint@8.49.0)(typescript@5.1.6)
:
...
@@ -9201,7 +9205,7 @@ packages:
...
@@ -9201,7 +9205,7 @@ packages:
solc
:
0.7.3(debug@4.3.4)
solc
:
0.7.3(debug@4.3.4)
source-map-support
:
0.5.21
source-map-support
:
0.5.21
stacktrace-parser
:
0.1.10
stacktrace-parser
:
0.1.10
ts-node
:
10.9.1(@types/node@20.6.
2
)(typescript@5.2.2)
ts-node
:
10.9.1(@types/node@20.6.
3
)(typescript@5.2.2)
tsort
:
0.0.1
tsort
:
0.0.1
typescript
:
5.2.2
typescript
:
5.2.2
undici
:
5.24.0
undici
:
5.24.0
...
@@ -13976,7 +13980,7 @@ packages:
...
@@ -13976,7 +13980,7 @@ packages:
yn
:
3.1.1
yn
:
3.1.1
dev
:
true
dev
:
true
/ts-node@10.9.1(@types/node@20.6.
2
)(typescript@5.2.2)
:
/ts-node@10.9.1(@types/node@20.6.
3
)(typescript@5.2.2)
:
resolution
:
{
integrity
:
sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
}
resolution
:
{
integrity
:
sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
}
hasBin
:
true
hasBin
:
true
peerDependencies
:
peerDependencies
:
...
@@ -13995,7 +13999,7 @@ packages:
...
@@ -13995,7 +13999,7 @@ packages:
'
@tsconfig/node12'
:
1.0.11
'
@tsconfig/node12'
:
1.0.11
'
@tsconfig/node14'
:
1.0.3
'
@tsconfig/node14'
:
1.0.3
'
@tsconfig/node16'
:
1.0.4
'
@tsconfig/node16'
:
1.0.4
'
@types/node'
:
20.6.
2
'
@types/node'
:
20.6.
3
acorn
:
8.10.0
acorn
:
8.10.0
acorn-walk
:
8.2.0
acorn-walk
:
8.2.0
arg
:
4.1.3
arg
:
4.1.3
...
...
ufm-test-services/docker-compose.yml
View file @
e422c544
...
@@ -35,7 +35,8 @@ services:
...
@@ -35,7 +35,8 @@ services:
environment
:
environment
:
-
GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PWD}
-
GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PWD}
volumes
:
volumes
:
-
./datasources.yml:/etc/grafana/provisioning/datasources/datasources.yaml
-
./grafana/provisioning:/etc/grafana/provisioning
-
./grafana/dashboards:/var/lib/grafana/dashboards
security_opt
:
security_opt
:
-
"
no-new-privileges:true"
-
"
no-new-privileges:true"
...
...
ufm-test-services/grafana/dashboards/metamask.json
0 → 100644
View file @
e422c544
{
"annotations"
:
{
"list"
:
[
{
"builtIn"
:
1
,
"datasource"
:
{
"type"
:
"grafana"
,
"uid"
:
"-- Grafana --"
},
"enable"
:
true
,
"hide"
:
true
,
"iconColor"
:
"rgba(0, 211, 255, 1)"
,
"name"
:
"Annotations & Alerts"
,
"type"
:
"dashboard"
}
]
},
"editable"
:
true
,
"fiscalYearStartMonth"
:
0
,
"graphTooltip"
:
0
,
"links"
:
[],
"liveNow"
:
false
,
"panels"
:
[
{
"datasource"
:
{
"type"
:
"prometheus"
,
"uid"
:
"PBFA97CFB590B2093"
},
"fieldConfig"
:
{
"defaults"
:
{
"color"
:
{
"mode"
:
"thresholds"
},
"mappings"
:
[],
"thresholds"
:
{
"mode"
:
"absolute"
,
"steps"
:
[
{
"color"
:
"red"
,
"value"
:
null
},
{
"color"
:
"yellow"
,
"value"
:
1
},
{
"color"
:
"green"
,
"value"
:
4
}
]
}
},
"overrides"
:
[]
},
"gridPos"
:
{
"h"
:
5
,
"w"
:
6
,
"x"
:
0
,
"y"
:
0
},
"id"
:
1
,
"options"
:
{
"orientation"
:
"auto"
,
"reduceOptions"
:
{
"calcs"
:
[
"lastNotNull"
],
"fields"
:
""
,
"values"
:
false
},
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
},
"pluginVersion"
:
"10.1.2"
,
"targets"
:
[
{
"datasource"
:
{
"type"
:
"prometheus"
,
"uid"
:
"PBFA97CFB590B2093"
},
"disableTextWrap"
:
false
,
"editorMode"
:
"builder"
,
"expr"
:
"metamask_tx_success"
,
"fullMetaSearch"
:
false
,
"includeNullMetadata"
:
true
,
"instant"
:
false
,
"legendFormat"
:
"__auto"
,
"range"
:
true
,
"refId"
:
"A"
,
"useBackend"
:
false
}
],
"title"
:
"Number of Successful Transaction Since Last Failure"
,
"type"
:
"gauge"
},
{
"datasource"
:
{
"type"
:
"prometheus"
,
"uid"
:
"PBFA97CFB590B2093"
},
"fieldConfig"
:
{
"defaults"
:
{
"color"
:
{
"mode"
:
"thresholds"
},
"mappings"
:
[],
"thresholds"
:
{
"mode"
:
"absolute"
,
"steps"
:
[
{
"color"
:
"text"
,
"value"
:
null
},
{
"color"
:
"red"
,
"value"
:
1
}
]
}
},
"overrides"
:
[]
},
"gridPos"
:
{
"h"
:
5
,
"w"
:
6
,
"x"
:
6
,
"y"
:
0
},
"id"
:
2
,
"options"
:
{
"orientation"
:
"auto"
,
"reduceOptions"
:
{
"calcs"
:
[
"lastNotNull"
],
"fields"
:
""
,
"values"
:
false
},
"showThresholdLabels"
:
false
,
"showThresholdMarkers"
:
true
},
"pluginVersion"
:
"10.1.2"
,
"targets"
:
[
{
"datasource"
:
{
"type"
:
"prometheus"
,
"uid"
:
"PBFA97CFB590B2093"
},
"disableTextWrap"
:
false
,
"editorMode"
:
"builder"
,
"expr"
:
"metamask_tx_failure"
,
"fullMetaSearch"
:
false
,
"includeNullMetadata"
:
true
,
"instant"
:
false
,
"legendFormat"
:
"__auto"
,
"range"
:
true
,
"refId"
:
"A"
,
"useBackend"
:
false
}
],
"title"
:
"Number of Failed Transactions Since Last Success"
,
"type"
:
"gauge"
}
],
"refresh"
:
"5s"
,
"schemaVersion"
:
38
,
"style"
:
"dark"
,
"tags"
:
[],
"templating"
:
{
"list"
:
[]
},
"time"
:
{
"from"
:
"now-6h"
,
"to"
:
"now"
},
"timepicker"
:
{},
"timezone"
:
""
,
"title"
:
"UFM: Metamask"
,
"uid"
:
"f66f7076-c724-4f81-8ff9-58d6d99f2716"
,
"version"
:
1
,
"weekStart"
:
""
}
ufm-test-services/grafana/provisioning/dashboards/all.yml
0 → 100644
View file @
e422c544
apiVersion
:
1
providers
:
-
name
:
'
default'
orgId
:
1
folder
:
'
'
type
:
file
disableDeletion
:
false
options
:
path
:
/var/lib/grafana/dashboards
ufm-test-services/
date
sources.yml
→
ufm-test-services/
grafana/provisioning/datasources/data
sources.yml
View file @
e422c544
File moved
ufm-test-services/metamask/README.md
0 → 100644
View file @
e422c544
# User Facing Monitoring - Metamask Tests
## Running Locally
### Building Docker Image
```
bash
docker build
-t
ufm-test-service-metamask
.
```
### Running the Docker Container on MacOS
The following steps were taken from
[
here
](
https://www.oddbird.net/2022/11/30/headed-playwright-in-docker/#macos
)
Apple’s operating system doesn’t include a built-in XServer, but we can use
[
XQuartz
](
https://www.xquartz.org/
)
to provide one:
1.
Install XQuartz:
`brew install --cask xquartz``
2. Open XQuartz, go to `
Preferences -> Security
`, and check `
Allow connections from network clients
`
3. Restart your computer (restarting XQuartz might not be enough)
4. Start XQuartz by executing `
xhost +localhost
` in your terminal
5. Open Docker Desktop and edit settings to give access to `
/tmp/.X11-unix
` in `
Preferences -> Resources -> File sharing
`
Once XQuartz is running with the right permissions, you can populate the environment variable and socket Docker args:
`
``
bash
docker run --rm -it
\
-e DISPLAY=host.docker.internal:0
\
-v /tmp/.X11-unix:/tmp/.X11-unix
\
ufm-test-service-metamask
```
ufm-test-services/metamask/package.json
View file @
e422c544
...
@@ -20,10 +20,14 @@
...
@@ -20,10 +20,14 @@
"devDependencies"
:
{
"devDependencies"
:
{
"@metamask/test-dapp"
:
"^7.1.0"
,
"@metamask/test-dapp"
:
"^7.1.0"
,
"@playwright/test"
:
"1.37.1"
,
"@playwright/test"
:
"1.37.1"
,
"@synthetixio/synpress"
:
"3.7.2-beta.
5
"
,
"@synthetixio/synpress"
:
"3.7.2-beta.
7
"
,
"dotenv"
:
"^16.3.1"
,
"dotenv"
:
"^16.3.1"
,
"static-server"
:
"^2.2.1"
,
"static-server"
:
"^2.2.1"
,
"typescript"
:
"^5.1.6"
,
"typescript"
:
"^5.1.6"
,
"viem"
:
"^1.10.8"
"viem"
:
"^1.10.8"
},
"dependencies"
:
{
"prom-client"
:
"^14.2.0"
,
"zod"
:
"^3.22.2"
}
}
}
}
ufm-test-services/metamask/pnpm-lock.yaml
View file @
e422c544
This diff is collapsed.
Click to expand it.
ufm-test-services/metamask/tests/metamask.spec.ts
View file @
e422c544
import
'
dotenv/config
'
import
'
dotenv/config
'
import
{
z
}
from
'
zod
'
import
metamask
from
'
@synthetixio/synpress/commands/metamask.js
'
import
metamask
from
'
@synthetixio/synpress/commands/metamask.js
'
import
{
expect
,
test
,
type
Page
}
from
'
@playwright/test
'
import
{
expect
,
test
,
type
Page
}
from
'
@playwright/test
'
import
{
mnemonicToAccount
,
privateKeyToAccount
}
from
'
viem/accounts
'
import
{
mnemonicToAccount
,
privateKeyToAccount
}
from
'
viem/accounts
'
import
{
testWithSynpress
}
from
'
./testWithSynpressUtil
'
import
{
testWithSynpress
}
from
'
./testWithSynpressUtil
'
import
{
getMetamaskTxCounterValue
,
incrementMetamaskTxCounter
,
setMetamaskTxCounter
,
}
from
'
./prometheusUtils
'
const
env
=
z
.
object
({
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
:
z
.
string
(),
OP_GOERLI_RPC_URL
:
z
.
string
().
url
(),
METAMASK_DAPP_URL
:
z
.
string
().
url
()
}).
parse
(
process
.
env
)
const
expectedSender
=
const
expectedSender
=
process
.
env
.
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
?.
startsWith
(
'
0x
'
)
env
.
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
?.
startsWith
(
'
0x
'
)
?
privateKeyToAccount
(
?
privateKeyToAccount
(
process
.
env
.
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
as
`0x
${
string
}
`
env
.
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
as
`0x
${
string
}
`
).
address
.
toLowerCase
()
).
address
.
toLowerCase
()
:
mnemonicToAccount
(
:
mnemonicToAccount
(
process
.
env
.
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
as
string
env
.
METAMASK_SECRET_WORDS_OR_PRIVATEKEY
as
string
).
address
.
toLowerCase
()
).
address
.
toLowerCase
()
const
expectedRecipient
=
'
0x8fcfbe8953433fd1f2e8375ee99057833e4e1e9e
'
const
expectedRecipient
=
'
0x8fcfbe8953433fd1f2e8375ee99057833e4e1e9e
'
...
@@ -35,7 +47,7 @@ testWithSynpress('Add OP Goerli network', async () => {
...
@@ -35,7 +47,7 @@ testWithSynpress('Add OP Goerli network', async () => {
name
:
'
op-goerli
'
,
name
:
'
op-goerli
'
,
rpcUrls
:
{
rpcUrls
:
{
default
:
{
default
:
{
http
:
[
process
.
env
.
OP_GOERLI_RPC_URL
],
http
:
[
env
.
OP_GOERLI_RPC_URL
],
},
},
},
},
id
:
'
420
'
,
id
:
'
420
'
,
...
@@ -49,13 +61,26 @@ testWithSynpress('Add OP Goerli network', async () => {
...
@@ -49,13 +61,26 @@ testWithSynpress('Add OP Goerli network', async () => {
},
},
})
})
await
expect
(
sharedPage
.
locator
(
'
#chainId
'
)).
toHaveText
(
expectedChainId
)
try
{
await
expect
(
sharedPage
.
locator
(
'
#chainId
'
)).
toHaveText
(
expectedChainId
)
}
catch
(
error
)
{
await
setMetamaskTxCounter
(
true
,
0
)
await
incrementMetamaskTxCounter
(
false
)
throw
error
}
})
})
test
(
`Connect wallet with
${
expectedSender
}
`
,
async
()
=>
{
test
(
`Connect wallet with
${
expectedSender
}
`
,
async
()
=>
{
await
sharedPage
.
click
(
'
#connectButton
'
)
await
sharedPage
.
click
(
'
#connectButton
'
)
await
metamask
.
acceptAccess
()
await
metamask
.
acceptAccess
()
await
expect
(
sharedPage
.
locator
(
'
#accounts
'
)).
toHaveText
(
expectedSender
)
try
{
await
expect
(
sharedPage
.
locator
(
'
#accounts
'
)).
toHaveText
(
expectedSender
)
}
catch
(
error
)
{
await
setMetamaskTxCounter
(
true
,
0
)
await
incrementMetamaskTxCounter
(
false
)
throw
error
}
})
})
test
(
'
Send an EIP-1559 transaciton and verfiy success
'
,
async
()
=>
{
test
(
'
Send an EIP-1559 transaciton and verfiy success
'
,
async
()
=>
{
...
@@ -76,17 +101,14 @@ test('Send an EIP-1559 transaciton and verfiy success', async () => {
...
@@ -76,17 +101,14 @@ test('Send an EIP-1559 transaciton and verfiy success', async () => {
})
})
})
})
await
metamask
.
confirmTransaction
()
await
metamask
.
confirmTransaction
AndWaitForMining
()
const
txHash
=
await
txHashPromise
const
txHash
=
await
txHashPromise
// Waiting for Infura (Metamask given provider) to index our transaction
await
sharedPage
.
waitForTimeout
(
10
_000
)
// Metamask test dApp allows us access to the Metamask RPC provider via loading this URL.
// Metamask test dApp allows us access to the Metamask RPC provider via loading this URL.
// The RPC reponse will be populated onto the page that's loaded.
// The RPC reponse will be populated onto the page that's loaded.
// More info here: https://github.com/MetaMask/test-dapp/tree/main#usage
// More info here: https://github.com/MetaMask/test-dapp/tree/main#usage
await
sharedPage
.
goto
(
await
sharedPage
.
goto
(
`
${
process
.
env
.
METAMASK_DAPP_URL
}
/request.html?method=eth_getTransactionReceipt¶ms=["
${
txHash
}
"]`
`
${
env
.
METAMASK_DAPP_URL
}
/request.html?method=eth_getTransactionReceipt¶ms=["
${
txHash
}
"]`
)
)
// Waiting for RPC response to be populated on the page
// Waiting for RPC response to be populated on the page
...
@@ -98,5 +120,14 @@ test('Send an EIP-1559 transaciton and verfiy success', async () => {
...
@@ -98,5 +120,14 @@ test('Send an EIP-1559 transaciton and verfiy success', async () => {
''
''
)
)
)
)
expect
(
transaction
.
status
).
toBe
(
'
0x1
'
)
try
{
expect
(
transaction
.
status
).
toBe
(
'
0x1
'
)
await
setMetamaskTxCounter
(
false
,
0
)
await
incrementMetamaskTxCounter
(
true
)
}
catch
(
error
)
{
await
setMetamaskTxCounter
(
true
,
0
)
await
incrementMetamaskTxCounter
(
false
)
throw
error
}
})
})
ufm-test-services/metamask/tests/prometheusUtils.ts
0 → 100644
View file @
e422c544
import
'
dotenv/config
'
import
{
z
}
from
'
zod
'
import
{
Counter
,
Pushgateway
}
from
'
prom-client
'
const
env
=
z
.
object
({
PROMETHEUS_SERVER_URL
:
z
.
string
().
url
(),
PROMETHEUS_PUSHGATEWAY_URL
:
z
.
string
().
url
(),
})
.
parse
(
process
.
env
)
const
txSuccessMetricName
=
'
metamask_tx_success
'
const
txFailureMetricName
=
'
metamask_tx_failuree
'
const
txSuccessCounter
=
new
Counter
({
name
:
txSuccessMetricName
,
help
:
'
A counter signifying the number of successful transactions sent with Metamask since last failure
'
,
})
const
txFailureCounter
=
new
Counter
({
name
:
txFailureMetricName
,
help
:
'
A counter signifying the number of failed transactions sent with Metamask since last successful transaction
'
,
})
export
const
getMetamaskTxCounterValue
=
async
(
isSuccess
:
boolean
)
=>
{
const
metricName
=
isSuccess
?
txSuccessMetricName
:
txFailureMetricName
const
prometheusMetricQuery
=
`
${
env
.
PROMETHEUS_SERVER_URL
}
/api/v1/query?query=
${
metricName
}
`
const
response
=
await
fetch
(
prometheusMetricQuery
)
if
(
!
response
.
ok
)
{
console
.
error
(
response
.
status
)
console
.
error
(
response
.
statusText
)
throw
new
Error
(
`Failed to fetch metric from:
${
prometheusMetricQuery
}
`
)
}
// The following is an example of the expect response from prometheusMetricQuery
// for response.json().data.result[0]:
// [
// {
// metric: {
// __name__: 'metamask_tx_success',
// exported_job: 'metamask_tx_count',
// instance: 'pushgateway:9091',
// job: 'pushgateway'
// },
// value: [ 1695250414.474, '0' ]
// }
// ]
try
{
const
responseJson
=
z
.
object
({
data
:
z
.
object
({
result
:
z
.
array
(
z
.
object
({
value
:
z
.
tuple
([
z
.
number
(),
z
.
number
().
or
(
z
.
string
().
transform
((
value
)
=>
parseInt
(
value
))),
]),
})
),
}),
})
.
parse
(
await
response
.
json
())
return
responseJson
.
data
.
result
[
0
].
value
[
1
]
}
catch
(
error
)
{
if
(
error
.
message
===
"
Cannot read properties of undefined (reading 'value')
"
)
{
console
.
warn
(
`No data found for metric
${
metricName
}
in Prometheus`
)
return
undefined
}
throw
error
}
}
export
const
setMetamaskTxCounter
=
async
(
isSuccess
:
boolean
,
valueToSetTo
:
number
)
=>
{
const
metricName
=
isSuccess
?
txSuccessMetricName
:
txFailureMetricName
const
txCounter
=
isSuccess
?
txSuccessCounter
:
txFailureCounter
txCounter
.
reset
()
console
.
log
(
`Setting
${
metricName
}
to
${
valueToSetTo
}
`
)
txCounter
.
inc
(
valueToSetTo
)
const
pushGateway
=
new
Pushgateway
(
env
.
PROMETHEUS_PUSHGATEWAY_URL
)
await
pushGateway
.
pushAdd
({
jobName
:
'
metamask_tx_count
'
})
}
export
const
incrementMetamaskTxCounter
=
async
(
isSuccess
:
boolean
)
=>
{
const
metricName
=
isSuccess
?
txSuccessMetricName
:
txFailureMetricName
const
currentMetricValue
=
(
await
getMetamaskTxCounterValue
(
true
))
??
0
console
.
log
(
`Current value of
${
metricName
}
is
${
currentMetricValue
}
, incrementing to
${
currentMetricValue
+
1
}
`
)
await
setMetamaskTxCounter
(
isSuccess
,
currentMetricValue
+
1
)
}
ufm-test-services/prometheus.yml
View file @
e422c544
global
:
global
:
scrape_interval
:
5
s
scrape_interval
:
2
s
scrape_configs
:
scrape_configs
:
-
job_name
:
'
pushgateway'
-
job_name
:
'
pushgateway'
...
...
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