Skip to content

Commit 4a3ef86

Browse files
committed
feat: add aabundler
1 parent 7e17050 commit 4a3ef86

File tree

4 files changed

+108
-92
lines changed

4 files changed

+108
-92
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ help:
99
run-cli:
1010
$(GORUN) ./cmd/betsy/main.go
1111

12+
run-cli-aa:
13+
$(GORUN) ./cmd/betsy/main.go --bundler aabundler
14+
1215
run-cli-dev:
1316
$(GORUN) ./cmd/betsy/main.go --log DEBUG --debug
1417

cmd/betsy/main.go

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"github.com/rs/zerolog/log"
16+
"github.com/transeptorlabs/betsy/internal/config"
1617
"github.com/transeptorlabs/betsy/internal/docker"
1718
"github.com/transeptorlabs/betsy/internal/mempool"
1819
"github.com/transeptorlabs/betsy/internal/server"
@@ -55,52 +56,7 @@ func main() {
5556
EnableBashCompletion: true,
5657
HideVersion: false,
5758
HideHelp: false,
58-
Flags: []cli.Flag{
59-
&cli.StringFlag{
60-
Name: "log.level",
61-
Usage: "Enable debug mode on server",
62-
Aliases: []string{"log"},
63-
Value: "INFO",
64-
Required: false,
65-
Category: "Logger selection:",
66-
},
67-
&cli.BoolFlag{
68-
Name: "debug",
69-
Usage: "Enable debug mode on server",
70-
Aliases: []string{"d"},
71-
Value: false,
72-
Required: false,
73-
Category: "Http server selection:",
74-
},
75-
&cli.UintFlag{
76-
Name: "http.port",
77-
Usage: "HTTP server listening port",
78-
Required: false,
79-
Value: 8080,
80-
Category: "Http server selection:",
81-
},
82-
&cli.UintFlag{
83-
Name: "eth.port",
84-
Usage: "ETH client network port",
85-
Required: false,
86-
Value: 8545,
87-
Category: "ETH client selection:",
88-
},
89-
&cli.StringFlag{
90-
Name: "bundler",
91-
Usage: "ERC 4337 bundler",
92-
Required: false,
93-
Value: "transeptor",
94-
Category: "ERC 4337 bundler selection:",
95-
},
96-
&cli.UintFlag{
97-
Name: "bundler.port",
98-
Usage: "ERC 4337 bundler listening port",
99-
Required: false,
100-
Value: 4337,
101-
Category: "ERC 4337 bundler selection:",
102-
},
103-
},
59+
Flags: config.BetsyFlags,
10460
Before: func(cCtx *cli.Context) error {
10561
log.Logger, err = logger.GetLogger(cCtx.String("log.level"))
10662
if err != nil {

internal/config/config.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package config
2+
3+
import "github.com/urfave/cli/v2"
4+
5+
// BetsyFlags is the list of flags that can be passed to the Betsy command line
6+
var BetsyFlags = []cli.Flag{
7+
&cli.StringFlag{
8+
Name: "log.level",
9+
Usage: "Enable debug mode on server",
10+
Aliases: []string{"log"},
11+
Value: "INFO",
12+
Required: false,
13+
Category: "Logger selection:",
14+
},
15+
&cli.BoolFlag{
16+
Name: "debug",
17+
Usage: "Enable debug mode on server",
18+
Aliases: []string{"d"},
19+
Value: false,
20+
Required: false,
21+
Category: "Http server selection:",
22+
},
23+
&cli.UintFlag{
24+
Name: "http.port",
25+
Usage: "HTTP server listening port",
26+
Required: false,
27+
Value: 8080,
28+
Category: "Http server selection:",
29+
},
30+
&cli.UintFlag{
31+
Name: "eth.port",
32+
Usage: "ETH client network port",
33+
Required: false,
34+
Value: 8545,
35+
Category: "ETH client selection:",
36+
},
37+
&cli.StringFlag{
38+
Name: "bundler",
39+
Usage: "ERC 4337 bundler",
40+
Required: false,
41+
Value: "transeptor",
42+
Category: "ERC 4337 bundler selection:",
43+
},
44+
&cli.UintFlag{
45+
Name: "bundler.port",
46+
Usage: "ERC 4337 bundler listening port",
47+
Required: false,
48+
Value: 4337,
49+
Category: "ERC 4337 bundler selection:",
50+
},
51+
}

internal/docker/docker.go

Lines changed: 52 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const BundlerNodeMnemonicPlaceHolder = "$MNEMONIC"
3030

3131
// ContainerManager manages containers
3232
type ContainerManager struct {
33-
supportedImages map[string]ContainerDetails
33+
supportedImages map[string]*ContainerDetails
3434
client *client.Client
3535
EthNodePort string
3636
CoinbaseKeystoreFile string
@@ -56,7 +56,7 @@ func NewContainerManager() (*ContainerManager, error) {
5656
}
5757

5858
return &ContainerManager{
59-
supportedImages: map[string]ContainerDetails{
59+
supportedImages: map[string]*ContainerDetails{
6060
"transeptor": {
6161
containerName: "betsy-transeptor",
6262
ContainerID: "",
@@ -78,6 +78,20 @@ func NewContainerManager() (*ContainerManager, error) {
7878
ExposedPorts: nil,
7979
NodeType: "bundler",
8080
},
81+
"aabundler": {
82+
containerName: "betsy-aabundler",
83+
ContainerID: "",
84+
imageName: "accountabstraction/bundler:0.7.0",
85+
IsRunning: false,
86+
Cmd: []string{
87+
"--network", "http://host.docker.internal:" + EthNodePortPlaceHolder,
88+
"--entryPoint", BundlerNodeEPAddressPlaceHolder,
89+
"--beneficiary", BundlerNodeBeneficiaryAddressPlaceHolder,
90+
},
91+
Env: []string{},
92+
ExposedPorts: nil,
93+
NodeType: "bundler",
94+
},
8195
"geth": {
8296
containerName: "betsy-geth",
8397
ContainerID: "",
@@ -197,6 +211,35 @@ func (cm *ContainerManager) doPullImage(ctx context.Context, imageName string) (
197211
return true, nil
198212
}
199213

214+
func (cm *ContainerManager) doReplaceBundlerPlaceHolders(containerDetails *ContainerDetails, bwd wallet.BundlerWalletDetails) {
215+
placeholders := map[string]string{
216+
BundlerNodeEPAddressPlaceHolder: bwd.EntryPointAddress.Hex(),
217+
BundlerNodeBeneficiaryAddressPlaceHolder: bwd.Beneficiary.Hex(),
218+
BundlerNodeMnemonicPlaceHolder: bwd.Mnemonic,
219+
EthNodePortPlaceHolder: cm.EthNodePort,
220+
}
221+
222+
// Replace placeholders in Cmd slice
223+
for placeholder, value := range placeholders {
224+
replacePlaceHolderInSlice(&containerDetails.Cmd, placeholder, value)
225+
}
226+
227+
// Replace placeholders in Env slice
228+
229+
for placeholder, value := range placeholders {
230+
replacePlaceHolderInSlice(&containerDetails.Env, placeholder, value)
231+
}
232+
}
233+
234+
// replacePlaceHolderInSlice finds and replaces a placeholder in a slice of strings.
235+
func replacePlaceHolderInSlice(slice *[]string, placeholder, replacement string) {
236+
for i, item := range *slice {
237+
if strings.Contains(item, placeholder) {
238+
(*slice)[i] = strings.Replace(item, placeholder, replacement, 1)
239+
}
240+
}
241+
}
242+
200243
// RunContainerInTheBackground runs a Docker container in the background given its image and host port to bind
201244
func (cm *ContainerManager) RunContainerInTheBackground(ctx context.Context, image string, hostPort string) (bool, error) {
202245
imageFound, ok := cm.supportedImages[image]
@@ -206,37 +249,11 @@ func (cm *ContainerManager) RunContainerInTheBackground(ctx context.Context, ima
206249

207250
// Update bundler node cmd with ethNode port
208251
if imageFound.NodeType == "bundler" {
209-
foundIndexPort := 0
210-
for index, item := range imageFound.Cmd {
211-
if strings.HasSuffix(item, EthNodePortPlaceHolder) {
212-
foundIndexPort = index
213-
break
214-
}
215-
}
216-
imageFound.Cmd[foundIndexPort] = strings.Replace(imageFound.Cmd[foundIndexPort], EthNodePortPlaceHolder, cm.EthNodePort, 1)
217-
218-
bundlerDetails := ctx.Value(BundlerNodeWalletDetails).(wallet.BundlerWalletDetails)
219-
foundIndexBeneficiary := 0
220-
foundIndexMnemonic := 0
221-
foundIndexEntryPointAddress := 0
222-
for index, item := range imageFound.Env {
223-
if strings.HasSuffix(item, BundlerNodeBeneficiaryAddressPlaceHolder) {
224-
foundIndexBeneficiary = index
225-
}
226-
227-
if strings.Contains(item, BundlerNodeMnemonicPlaceHolder) {
228-
foundIndexMnemonic = index
229-
}
230-
231-
if strings.Contains(item, BundlerNodeEPAddressPlaceHolder) {
232-
foundIndexEntryPointAddress = index
233-
}
234-
}
235-
imageFound.Env[foundIndexEntryPointAddress] = strings.Replace(imageFound.Env[foundIndexEntryPointAddress], BundlerNodeEPAddressPlaceHolder, bundlerDetails.EntryPointAddress.Hex(), 1)
236-
imageFound.Env[foundIndexBeneficiary] = strings.Replace(imageFound.Env[foundIndexBeneficiary], BundlerNodeBeneficiaryAddressPlaceHolder, bundlerDetails.Beneficiary.Hex(), 1)
237-
imageFound.Env[foundIndexMnemonic] = strings.Replace(imageFound.Env[foundIndexMnemonic], BundlerNodeMnemonicPlaceHolder, bundlerDetails.Mnemonic, 1)
252+
bwd := ctx.Value(BundlerNodeWalletDetails).(wallet.BundlerWalletDetails)
253+
cm.doReplaceBundlerPlaceHolders(imageFound, bwd)
238254
}
239255

256+
// Create and start the container
240257
containerPort := hostPort + "/tcp"
241258
config := &container.Config{
242259
Image: imageFound.imageName,
@@ -245,13 +262,6 @@ func (cm *ContainerManager) RunContainerInTheBackground(ctx context.Context, ima
245262
ExposedPorts: nat.PortSet{
246263
nat.Port(containerPort): struct{}{},
247264
},
248-
// TODO: Use health check for bundlers and eth node
249-
// HealthCheck: &container.HealthConfig{
250-
// Test: []string{"CMD", "curl", "-f", "http://localhost:" + hostPort},
251-
// Interval: 10 * time.Second,
252-
// Timeout: 5 * time.Second,
253-
// Retries: 5,
254-
// },
255265
}
256266

257267
hostConfig := &container.HostConfig{
@@ -276,15 +286,11 @@ func (cm *ContainerManager) RunContainerInTheBackground(ctx context.Context, ima
276286

277287
// Update the container details
278288
log.Debug().Msgf("%s Container ID successfully started: %s\n", image, resp.ID)
279-
cm.supportedImages[image] = ContainerDetails{
280-
imageName: imageFound.imageName,
281-
Cmd: imageFound.Cmd,
282-
ExposedPorts: nat.PortSet{
283-
nat.Port(containerPort): struct{}{},
284-
},
285-
ContainerID: resp.ID,
286-
IsRunning: true,
289+
imageFound.ExposedPorts = nat.PortSet{
290+
nat.Port(containerPort): struct{}{},
287291
}
292+
imageFound.ContainerID = resp.ID
293+
imageFound.IsRunning = true
288294

289295
// Update EthNodeReady channel and signal that eth is ready by closing the channel
290296
if imageFound.NodeType == "eth" {

0 commit comments

Comments
 (0)