Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding implementation and tests for admin write commands. #252

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/Layr-Labs/eigenlayer-contracts v0.3.2-mainnet-rewards
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210234612-fdae59339a81
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241211204646-f49e96f7ee7a
github.com/blang/semver/v4 v4.0.0
github.com/consensys/gnark-crypto v0.12.1
github.com/ethereum/go-ethereum v1.14.5
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7 h1:1kehcG
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210234612-fdae59339a81 h1:max9ka+a5hx9/i/mbH1Y9GToXOCEtfsrt1BX02CAdYA=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210234612-fdae59339a81/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241211204347-52f4546fdec2 h1:NY7ol96kHl0btYNS8IM8XLYa+PjHs8gMHoISwHGTWCg=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241211204347-52f4546fdec2/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241211204646-f49e96f7ee7a h1:U1pibFpUsMfL8h9EGrHtm/z94nKKuEvLdWEpkCkCZr4=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241211204646-f49e96f7ee7a/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
Expand Down
125 changes: 124 additions & 1 deletion pkg/user/admin/accept.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,156 @@
package admin

import (
"context"
"sort"

"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common"
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"
"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
"github.com/Layr-Labs/eigensdk-go/logging"
eigenSdkUtils "github.com/Layr-Labs/eigensdk-go/utils"
gethcommon "github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"

"github.com/urfave/cli/v2"
)

func AcceptCmd() *cli.Command {
type AcceptAdminWriter interface {
AcceptAdmin(
ctx context.Context,
request elcontracts.AcceptAdminRequest,
) (*gethtypes.Receipt, error)
}

func AcceptCmd(generator func(logging.Logger, *acceptAdminConfig) (AcceptAdminWriter, error)) *cli.Command {
acceptCmd := &cli.Command{
Name: "accept-admin",
Usage: "user admin accept-admin --account-address <AccountAddress>",
UsageText: "Accepts a user to become admin who is currently pending admin acceptance.",
Description: `
Accepts a user to become admin who is currently pending admin acceptance.
`,
Action: func(c *cli.Context) error {
return acceptAdmin(c, generator)
},
After: telemetry.AfterRunAction(),
Flags: acceptFlags(),
}

return acceptCmd
}

func acceptAdmin(
cliCtx *cli.Context,
generator func(logging.Logger, *acceptAdminConfig) (AcceptAdminWriter, error),
) error {
ctx := cliCtx.Context
logger := common.GetLogger(cliCtx)

config, err := readAndValidateAcceptAdminConfig(cliCtx, logger)
if err != nil {
return eigenSdkUtils.WrapError("failed to read and validate user admin accept config", err)
}
cliCtx.App.Metadata["network"] = config.ChainID.String()
elWriter, err := generator(logger, config)
if err != nil {
return err
}

receipt, err := elWriter.AcceptAdmin(
ctx,
elcontracts.AcceptAdminRequest{AccountAddress: config.AccountAddress, WaitForReceipt: true},
)
if err != nil {
return err
}
common.PrintTransactionInfo(receipt.TxHash.String(), config.ChainID)
return nil
}

func readAndValidateAcceptAdminConfig(
cliContext *cli.Context,
logger logging.Logger,
) (*acceptAdminConfig, error) {
accountAddress := gethcommon.HexToAddress(cliContext.String(AccountAddressFlag.Name))
ethRpcUrl := cliContext.String(flags.ETHRpcUrlFlag.Name)
network := cliContext.String(flags.NetworkFlag.Name)
environment := cliContext.String(flags.EnvironmentFlag.Name)
if environment == "" {
environment = common.GetEnvFromNetwork(network)
}
signerConfig, err := common.GetSignerConfig(cliContext, logger)
if err != nil {
// We don't want to throw error since people can still use it to generate the claim
// without broadcasting it
logger.Debugf("Failed to get signer config: %s", err)
}

chainID := utils.NetworkNameToChainId(network)
permissionManagerAddress := cliContext.String(PermissionControllerAddressFlag.Name)

if common.IsEmptyString(permissionManagerAddress) {
permissionManagerAddress, err = common.GetPermissionManagerAddress(utils.NetworkNameToChainId(network))
if err != nil {
return nil, err
}
}

logger.Debugf(
"Env: %s, network: %s, chain ID: %s, PermissionManager address: %s",
environment,
network,
chainID,
permissionManagerAddress,
)

return &acceptAdminConfig{
Network: network,
RPCUrl: ethRpcUrl,
AccountAddress: accountAddress,
PermissionManagerAddress: gethcommon.HexToAddress(permissionManagerAddress),
SignerConfig: *signerConfig,
ChainID: chainID,
Environment: environment,
}, nil
}

func acceptFlags() []cli.Flag {
cmdFlags := []cli.Flag{
&flags.VerboseFlag,
&AccountAddressFlag,
&flags.OutputTypeFlag,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you going to add broadcast flag and corresponding feature later?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, going to do a sweep over all flags in a separate PR.

&flags.OutputFileFlag,
&flags.NetworkFlag,
&flags.EnvironmentFlag,
&flags.ETHRpcUrlFlag,
&PermissionControllerAddressFlag,
}
sort.Sort(cli.FlagsByName(cmdFlags))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did not realize before but you should append signer flags first and then sort - so that all flags are sorted

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gonna pick this up in the flag review.

return append(cmdFlags, flags.GetSignerFlags()...)
}

func generateAcceptAdminWriter(
prompter utils.Prompter,
) func(logger logging.Logger, config *acceptAdminConfig) (AcceptAdminWriter, error) {
return func(logger logging.Logger, config *acceptAdminConfig) (AcceptAdminWriter, error) {
ethClient, err := ethclient.Dial(config.RPCUrl)
if err != nil {
return nil, eigenSdkUtils.WrapError("failed to create new eth client", err)
}
return common.GetELWriter(
config.AccountAddress,
&config.SignerConfig,
ethClient,
elcontracts.Config{
PermissionsControllerAddress: config.PermissionManagerAddress,
},
prompter,
config.ChainID,
logger,
)
}
}
106 changes: 106 additions & 0 deletions pkg/user/admin/accept_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package admin

import (
"context"
"errors"
"testing"

"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
"github.com/Layr-Labs/eigensdk-go/logging"
gethcommon "github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/assert"

"github.com/urfave/cli/v2"
)

type mockAcceptAdminWriter struct {
acceptAdminFunc func(ctx context.Context, request elcontracts.AcceptAdminRequest) (*gethtypes.Receipt, error)
}

func (m *mockAcceptAdminWriter) AcceptAdmin(
ctx context.Context,
request elcontracts.AcceptAdminRequest,
) (*gethtypes.Receipt, error) {
return m.acceptAdminFunc(ctx, request)
}

func generateMockAcceptAdminWriter(
receipt *gethtypes.Receipt,
err error,
) func(logging.Logger, *acceptAdminConfig) (AcceptAdminWriter, error) {
return func(logger logging.Logger, config *acceptAdminConfig) (AcceptAdminWriter, error) {
return &mockAcceptAdminWriter{
acceptAdminFunc: func(ctx context.Context, request elcontracts.AcceptAdminRequest) (*gethtypes.Receipt, error) {
return receipt, err
},
}, nil
}
}

func TestAcceptCmd_Success(t *testing.T) {
mockReceipt := &gethtypes.Receipt{
TxHash: gethcommon.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"),
}

app := cli.NewApp()
app.Commands = []*cli.Command{
AcceptCmd(generateMockAcceptAdminWriter(mockReceipt, nil)),
}

args := []string{
"TestAcceptCmd_Success",
"accept-admin",
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12",
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
"--network", "holesky",
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
}

err := app.Run(args)
assert.NoError(t, err)
}

func TestAcceptCmd_GeneratorError(t *testing.T) {
expectedError := "failed to create admin writer"
app := cli.NewApp()
app.Commands = []*cli.Command{
AcceptCmd(func(logger logging.Logger, config *acceptAdminConfig) (AcceptAdminWriter, error) {
return nil, errors.New(expectedError)
}),
}

args := []string{
"TestAcceptCmd_GeneratorError",
"accept-admin",
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12",
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
"--network", "holesky",
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
}

err := app.Run(args)
assert.Error(t, err)
assert.Contains(t, err.Error(), expectedError)
}

func TestAcceptCmd_AcceptAdminError(t *testing.T) {
expectedError := "error accepting admin"
app := cli.NewApp()
app.Commands = []*cli.Command{
AcceptCmd(generateMockAcceptAdminWriter(nil, errors.New(expectedError))),
}

args := []string{
"TestAcceptCmd_AcceptAdminError",
"accept-admin",
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12",
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
"--network", "holesky",
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
}

err := app.Run(args)
assert.Error(t, err)
assert.Contains(t, err.Error(), expectedError)
}
Loading
Loading