-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding admin read commands with unit tests.
- Loading branch information
Brandon Chatham
committed
Dec 11, 2024
1 parent
699d6a6
commit e7d3bfd
Showing
13 changed files
with
983 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,138 @@ | ||
package admin | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"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" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
|
||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
func IsAdminCmd() *cli.Command { | ||
isAdmin := &cli.Command{ | ||
type IsAdminReader interface { | ||
IsAdmin( | ||
ctx context.Context, | ||
accountAddress gethcommon.Address, | ||
pendingAdminAddress gethcommon.Address, | ||
) (bool, error) | ||
} | ||
|
||
func IsAdminCmd(readerGenerator func(logging.Logger, *isAdminConfig) (IsAdminReader, error)) *cli.Command { | ||
cmd := &cli.Command{ | ||
Name: "is-admin", | ||
Usage: "user admin is-admin --account-address <AccountAddress> --caller-address <CallerAddress>", | ||
UsageText: "Checks if a user is an admin.", | ||
Description: ` | ||
Checks if a user is an admin. | ||
`, | ||
After: telemetry.AfterRunAction(), | ||
Flags: []cli.Flag{ | ||
&flags.VerboseFlag, | ||
&AccountAddressFlag, | ||
&CallerAddressFlag, | ||
Action: func(c *cli.Context) error { | ||
return isAdmin(c, readerGenerator) | ||
}, | ||
After: telemetry.AfterRunAction(), | ||
Flags: IsAdminFlags(), | ||
} | ||
|
||
return cmd | ||
} | ||
|
||
func isAdmin(cliCtx *cli.Context, generator func(logging.Logger, *isAdminConfig) (IsAdminReader, error)) error { | ||
ctx := cliCtx.Context | ||
logger := common.GetLogger(cliCtx) | ||
|
||
config, err := readAndValidateIsAdminConfig(cliCtx, logger) | ||
if err != nil { | ||
return eigenSdkUtils.WrapError("failed to read and validate user can call config", err) | ||
} | ||
cliCtx.App.Metadata["network"] = config.ChainID.String() | ||
elReader, err := generator(logger, config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
result, err := elReader.IsAdmin(ctx, config.AccountAddress, config.AdminAddress) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("IsAdmin Result: %v\n", result) | ||
return nil | ||
} | ||
|
||
func readAndValidateIsAdminConfig(cliContext *cli.Context, logger logging.Logger) (*isAdminConfig, error) { | ||
accountAddress := gethcommon.HexToAddress(cliContext.String(AccountAddressFlag.Name)) | ||
adminAddress := gethcommon.HexToAddress(cliContext.String(AdminAddressFlag.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) | ||
} | ||
|
||
chainID := utils.NetworkNameToChainId(network) | ||
permissionManagerAddress := cliContext.String(PermissionControllerAddressFlag.Name) | ||
|
||
var err error | ||
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 isAdmin | ||
return &isAdminConfig{ | ||
Network: network, | ||
RPCUrl: ethRpcUrl, | ||
AccountAddress: accountAddress, | ||
AdminAddress: adminAddress, | ||
PermissionManagerAddress: gethcommon.HexToAddress(permissionManagerAddress), | ||
ChainID: chainID, | ||
Environment: environment, | ||
}, nil | ||
} | ||
|
||
func generateIsAdminReader(logger logging.Logger, config *isAdminConfig) (IsAdminReader, error) { | ||
ethClient, err := ethclient.Dial(config.RPCUrl) | ||
if err != nil { | ||
return nil, eigenSdkUtils.WrapError("failed to create new eth client", err) | ||
} | ||
elReader, err := elcontracts.NewReaderFromConfig( | ||
elcontracts.Config{ | ||
PermissionsControllerAddress: config.PermissionManagerAddress, | ||
}, | ||
ethClient, | ||
logger, | ||
) | ||
return elReader, err | ||
} | ||
|
||
func IsAdminFlags() []cli.Flag { | ||
cmdFlags := []cli.Flag{ | ||
&flags.VerboseFlag, | ||
&AccountAddressFlag, | ||
&CallerAddressFlag, | ||
&flags.OutputTypeFlag, | ||
&flags.OutputFileFlag, | ||
&PermissionControllerAddressFlag, | ||
&flags.NetworkFlag, | ||
&flags.EnvironmentFlag, | ||
&flags.ETHRpcUrlFlag, | ||
} | ||
sort.Sort(cli.FlagsByName(cmdFlags)) | ||
return cmdFlags | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package admin | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"testing" | ||
|
||
"github.com/Layr-Labs/eigensdk-go/logging" | ||
gethcommon "github.com/ethereum/go-ethereum/common" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
type mockIsAdminReader struct { | ||
isAdminFunc func(ctx context.Context, accountAddress gethcommon.Address, adminAddress gethcommon.Address) (bool, error) | ||
} | ||
|
||
func (m *mockIsAdminReader) IsAdmin( | ||
ctx context.Context, | ||
accountAddress gethcommon.Address, | ||
adminAddress gethcommon.Address, | ||
) (bool, error) { | ||
return m.isAdminFunc(ctx, accountAddress, adminAddress) | ||
} | ||
|
||
func generateMockIsAdminReader(result bool, err error) func(logging.Logger, *isAdminConfig) (IsAdminReader, error) { | ||
return func(logger logging.Logger, config *isAdminConfig) (IsAdminReader, error) { | ||
return &mockIsAdminReader{ | ||
isAdminFunc: func(ctx context.Context, accountAddress gethcommon.Address, adminAddress gethcommon.Address) (bool, error) { | ||
return result, err | ||
}, | ||
}, nil | ||
} | ||
} | ||
|
||
func TestIsAdminCmd_Success(t *testing.T) { | ||
app := cli.NewApp() | ||
app.Commands = []*cli.Command{ | ||
IsAdminCmd(generateMockIsAdminReader(true, nil)), | ||
} | ||
|
||
args := []string{ | ||
"TestIsAdminCmd_Success", | ||
"is-admin", | ||
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12", | ||
"--caller-address", "0x1234567890abcdef1234567890abcdef12345678", | ||
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/", | ||
"--network", "holesky", | ||
} | ||
|
||
err := app.Run(args) | ||
assert.NoError(t, err) | ||
} | ||
|
||
func TestIsAdminCmd_NotAdmin(t *testing.T) { | ||
app := cli.NewApp() | ||
app.Commands = []*cli.Command{ | ||
IsAdminCmd(generateMockIsAdminReader(false, nil)), | ||
} | ||
|
||
args := []string{ | ||
"TestIsAdminCmd_NotAdmin", | ||
"is-admin", | ||
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12", | ||
"--caller-address", "0x1234567890abcdef1234567890abcdef12345678", | ||
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/", | ||
"--network", "holesky", | ||
} | ||
|
||
err := app.Run(args) | ||
assert.NoError(t, err) | ||
} | ||
|
||
func TestIsAdminCmd_GeneratorError(t *testing.T) { | ||
expectedError := "failed to create admin reader" | ||
app := cli.NewApp() | ||
app.Commands = []*cli.Command{ | ||
IsAdminCmd(func(logger logging.Logger, config *isAdminConfig) (IsAdminReader, error) { | ||
return nil, errors.New(expectedError) | ||
}), | ||
} | ||
|
||
args := []string{ | ||
"TestIsAdminCmd_GeneratorError", | ||
"is-admin", | ||
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12", | ||
"--caller-address", "0x1234567890abcdef1234567890abcdef12345678", | ||
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/", | ||
"--network", "holesky", | ||
} | ||
|
||
err := app.Run(args) | ||
assert.Error(t, err) | ||
assert.Contains(t, err.Error(), expectedError) | ||
} | ||
|
||
func TestIsAdminCmd_IsAdminError(t *testing.T) { | ||
expectedError := "error checking admin status" | ||
app := cli.NewApp() | ||
app.Commands = []*cli.Command{ | ||
IsAdminCmd(generateMockIsAdminReader(false, errors.New(expectedError))), | ||
} | ||
|
||
args := []string{ | ||
"TestIsAdminCmd_IsAdminError", | ||
"is-admin", | ||
"--account-address", "0xabcdef1234567890abcdef1234567890abcdef12", | ||
"--caller-address", "0x1234567890abcdef1234567890abcdef12345678", | ||
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/", | ||
"--network", "holesky", | ||
} | ||
|
||
err := app.Run(args) | ||
assert.Error(t, err) | ||
assert.Contains(t, err.Error(), expectedError) | ||
} |
Oops, something went wrong.