-
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 implementation and tests for admin write commands. (#252)
Co-authored-by: Brandon Chatham <[email protected]>
- Loading branch information
Showing
21 changed files
with
1,023 additions
and
27 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
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, | ||
&flags.OutputFileFlag, | ||
&flags.NetworkFlag, | ||
&flags.EnvironmentFlag, | ||
&flags.ETHRpcUrlFlag, | ||
&PermissionControllerAddressFlag, | ||
} | ||
sort.Sort(cli.FlagsByName(cmdFlags)) | ||
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, | ||
) | ||
} | ||
} |
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,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) | ||
} |
Oops, something went wrong.