diff --git a/cmd/account/link_key/link_key.go b/cmd/account/link_key/link_key.go index 6be66976..d9899047 100644 --- a/cmd/account/link_key/link_key.go +++ b/cmd/account/link_key/link_key.go @@ -58,13 +58,13 @@ type initiateLinkingResponse struct { FunctionArgs []string `json:"functionArgs"` } -func Exec(ctx *runtime.Context, in Inputs) error { +func Exec(parentCtx context.Context, ctx *runtime.Context, in Inputs) error { h := newHandler(ctx, nil) if err := h.ValidateInputs(in); err != nil { return err } - return h.Execute(in) + return h.Execute(parentCtx, in) } func New(runtimeContext *runtime.Context) *cobra.Command { @@ -83,7 +83,7 @@ func New(runtimeContext *runtime.Context) *cobra.Command { return err } - return h.Execute(inputs) + return h.Execute(cmd.Context(), inputs) }, } settings.AddTxnTypeFlags(cmd) @@ -101,6 +101,7 @@ type handler struct { stdin io.Reader environmentSet *environments.EnvironmentSet wrc *client.WorkflowRegistryV2Client + execCtx context.Context validated bool @@ -109,28 +110,28 @@ type handler struct { } func newHandler(ctx *runtime.Context, stdin io.Reader) *handler { - h := handler{ + return &handler{ settings: ctx.Settings, credentials: ctx.Credentials, clientFactory: ctx.ClientFactory, log: ctx.Logger, environmentSet: ctx.EnvironmentSet, stdin: stdin, - wg: sync.WaitGroup{}, - wrcErr: nil, } +} + +func (h *handler) initWorkflowRegistryClient() error { h.wg.Add(1) go func() { defer h.wg.Done() - wrc, err := h.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.clientFactory.NewWorkflowRegistryV2Client(h.execCtx) if err != nil { h.wrcErr = fmt.Errorf("failed to create workflow registry client: %w", err) return } h.wrc = wrc }() - - return &h + return nil } func (h *handler) ResolveInputs(v *viper.Viper) (Inputs, error) { @@ -154,11 +155,16 @@ func (h *handler) ValidateInputs(in Inputs) error { return nil } -func (h *handler) Execute(in Inputs) error { +func (h *handler) Execute(ctx context.Context, in Inputs) error { if !h.validated { return fmt.Errorf("inputs not validated") } + h.execCtx = ctx + if err := h.initWorkflowRegistryClient(); err != nil { + return err + } + h.displayDetails() if in.WorkflowOwnerLabel == "" { @@ -191,7 +197,7 @@ func (h *handler) Execute(in Inputs) error { ui.Dim(fmt.Sprintf("Starting linking: owner=%s, label=%s", in.WorkflowOwner, in.WorkflowOwnerLabel)) - resp, err := h.callInitiateLinking(context.Background(), in) + resp, err := h.callInitiateLinking(h.execCtx, in) if err != nil { return err } @@ -296,10 +302,10 @@ func (h *handler) linkOwner(resp initiateLinkingResponse) error { } ownerAddr := common.HexToAddress(h.settings.Workflow.UserWorkflowSettings.WorkflowOwnerAddress) - if err := h.wrc.CanLinkOwner(ownerAddr, ts, proofBytes, sigBytes); err != nil { + if err := h.wrc.CanLinkOwner(h.execCtx, ownerAddr, ts, proofBytes, sigBytes); err != nil { return fmt.Errorf("link request verification failed: %w", err) } - txOut, err := h.wrc.LinkOwner(ts, proofBytes, sigBytes) + txOut, err := h.wrc.LinkOwner(h.execCtx, ts, proofBytes, sigBytes) if err != nil { return fmt.Errorf("LinkOwner failed: %w", err) } @@ -388,7 +394,7 @@ func (h *handler) checkIfAlreadyLinked() (bool, error) { ownerAddr := common.HexToAddress(h.settings.Workflow.UserWorkflowSettings.WorkflowOwnerAddress) ui.Dim("Checking existing registrations...") - linked, err := h.wrc.IsOwnerLinked(ownerAddr) + linked, err := h.wrc.IsOwnerLinked(h.execCtx, ownerAddr) if err != nil { return false, fmt.Errorf("failed to check owner link status: %w", err) } diff --git a/cmd/account/unlink_key/unlink_key.go b/cmd/account/unlink_key/unlink_key.go index 3c50e373..05afc0ca 100644 --- a/cmd/account/unlink_key/unlink_key.go +++ b/cmd/account/unlink_key/unlink_key.go @@ -61,6 +61,7 @@ type handler struct { stdin io.Reader environmentSet *environments.EnvironmentSet wrc *client.WorkflowRegistryV2Client + execCtx context.Context validated bool @@ -83,7 +84,7 @@ func New(runtimeContext *runtime.Context) *cobra.Command { if err := h.ValidateInputs(in); err != nil { return err } - return h.Execute(in) + return h.Execute(cmd.Context(), in) }, } settings.AddTxnTypeFlags(cmd) @@ -92,28 +93,28 @@ func New(runtimeContext *runtime.Context) *cobra.Command { } func newHandler(ctx *runtime.Context, stdin io.Reader) *handler { - h := handler{ + return &handler{ settings: ctx.Settings, credentials: ctx.Credentials, clientFactory: ctx.ClientFactory, log: ctx.Logger, environmentSet: ctx.EnvironmentSet, stdin: stdin, - wg: sync.WaitGroup{}, - wrcErr: nil, } +} + +func (h *handler) initWorkflowRegistryClient() error { h.wg.Add(1) go func() { defer h.wg.Done() - wrc, err := h.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.clientFactory.NewWorkflowRegistryV2Client(h.execCtx) if err != nil { h.wrcErr = fmt.Errorf("failed to create workflow registry client: %w", err) return } h.wrc = wrc }() - - return &h + return nil } func (h *handler) ResolveInputs(v *viper.Viper) (Inputs, error) { @@ -137,11 +138,16 @@ func (h *handler) ValidateInputs(in Inputs) error { return nil } -func (h *handler) Execute(in Inputs) error { +func (h *handler) Execute(ctx context.Context, in Inputs) error { if !h.validated { return fmt.Errorf("inputs not validated") } + h.execCtx = ctx + if err := h.initWorkflowRegistryClient(); err != nil { + return err + } + h.displayDetails() ui.Dim(fmt.Sprintf("Starting unlinking: owner=%s", in.WorkflowOwner)) @@ -181,7 +187,7 @@ func (h *handler) Execute(in Inputs) error { } } - resp, err := h.callInitiateUnlinking(context.Background(), in) + resp, err := h.callInitiateUnlinking(h.execCtx, in) if err != nil { return err } @@ -255,10 +261,10 @@ func (h *handler) unlinkOwner(owner string, resp initiateUnlinkingResponse) erro } addr := common.HexToAddress(owner) - if err := h.wrc.CanUnlinkOwner(addr, ts, sigBytes); err != nil { + if err := h.wrc.CanUnlinkOwner(h.execCtx, addr, ts, sigBytes); err != nil { return fmt.Errorf("unlink request verification failed: %w", err) } - txOut, err := h.wrc.UnlinkOwner(addr, ts, sigBytes) + txOut, err := h.wrc.UnlinkOwner(h.execCtx, addr, ts, sigBytes) if err != nil { return fmt.Errorf("UnlinkOwner failed: %w", err) } @@ -346,7 +352,7 @@ func (h *handler) unlinkOwner(owner string, resp initiateUnlinkingResponse) erro func (h *handler) checkIfAlreadyLinked() (bool, error) { ownerAddr := common.HexToAddress(h.settings.Workflow.UserWorkflowSettings.WorkflowOwnerAddress) - linked, err := h.wrc.IsOwnerLinked(ownerAddr) + linked, err := h.wrc.IsOwnerLinked(h.execCtx, ownerAddr) if err != nil { return false, fmt.Errorf("failed to check owner link status: %w", err) } diff --git a/cmd/client/client_factory.go b/cmd/client/client_factory.go index 82e75882..bb496a82 100644 --- a/cmd/client/client_factory.go +++ b/cmd/client/client_factory.go @@ -1,6 +1,7 @@ package client import ( + "context" "fmt" "strings" @@ -15,7 +16,7 @@ import ( ) type Factory interface { - NewWorkflowRegistryV2Client() (*WorkflowRegistryV2Client, error) + NewWorkflowRegistryV2Client(ctx context.Context) (*WorkflowRegistryV2Client, error) GetTxType() TxType GetSkipConfirmation() bool } @@ -32,7 +33,7 @@ func NewFactory(logger *zerolog.Logger, viper *viper.Viper) Factory { } } -func (f *factoryImpl) NewWorkflowRegistryV2Client() (*WorkflowRegistryV2Client, error) { +func (f *factoryImpl) NewWorkflowRegistryV2Client(ctx context.Context) (*WorkflowRegistryV2Client, error) { environmentSet, err := environments.New() if err != nil { return nil, fmt.Errorf("failed to load environment details: %w", err) @@ -60,7 +61,7 @@ func (f *factoryImpl) NewWorkflowRegistryV2Client() (*WorkflowRegistryV2Client, txcConfig, ) - typeAndVersion, err := workflowRegistryV2Client.TypeAndVersion() + typeAndVersion, err := workflowRegistryV2Client.TypeAndVersion(ctx) if err != nil { return workflowRegistryV2Client, fmt.Errorf("failed to get type and version of workflow registry contract at %s: %w", environmentSet.WorkflowRegistryAddress, err) } diff --git a/cmd/client/eth_client.go b/cmd/client/eth_client.go index dad74dca..7ee1a785 100644 --- a/cmd/client/eth_client.go +++ b/cmd/client/eth_client.go @@ -184,14 +184,16 @@ func readSethConfigFromFile(configPath string) (*seth.Config, error) { } func getChainID(rpcURL string) (uint64, error) { - client, err := rpc.DialContext(context.Background(), rpcURL) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + client, err := rpc.DialContext(ctx, rpcURL) if err != nil { return 0, err } defer client.Close() var chainID string - err = client.CallContext(context.Background(), &chainID, "eth_chainId") + err = client.CallContext(ctx, &chainID, "eth_chainId") if err != nil { return 0, err } diff --git a/cmd/client/tx.go b/cmd/client/tx.go index 1d7715cb..d280eaa0 100644 --- a/cmd/client/tx.go +++ b/cmd/client/tx.go @@ -1,6 +1,7 @@ package client import ( + "context" "encoding/json" "errors" "fmt" @@ -119,7 +120,7 @@ type RawTx struct { // return txOpts, nil //} -func (c *TxClient) executeTransactionByTxType(txFn func(opts *bind.TransactOpts) (*types.Transaction, error), funName string, validationEvent string, args ...any) (TxOutput, error) { +func (c *TxClient) executeTransactionByTxType(ctx context.Context, txFn func(opts *bind.TransactOpts) (*types.Transaction, error), funName string, validationEvent string, args ...any) (TxOutput, error) { switch c.config.TxType { case Regular: simulateTx, err := txFn(cmdCommon.SimTransactOpts()) @@ -138,7 +139,7 @@ func (c *TxClient) executeTransactionByTxType(txFn func(opts *bind.TransactOpts) Value: simulateTx.Value(), Data: simulateTx.Data(), } - estimatedGas, gasErr := c.EthClient.Client.EstimateGas(c.EthClient.Context, msg) + estimatedGas, gasErr := c.EthClient.Client.EstimateGas(ctx, msg) if gasErr != nil { c.Logger.Warn().Err(gasErr).Msg("Failed to estimate gas usage") } @@ -159,7 +160,7 @@ func (c *TxClient) executeTransactionByTxType(txFn func(opts *bind.TransactOpts) // Calculate and print total cost for sending the transaction on-chain if gasErr == nil { - gasPriceWei, gasPriceErr := c.EthClient.Client.SuggestGasPrice(c.EthClient.Context) + gasPriceWei, gasPriceErr := c.EthClient.Client.SuggestGasPrice(ctx) if gasPriceErr != nil { c.Logger.Warn().Err(gasPriceErr).Msg("Failed to fetch gas price") } else { @@ -189,7 +190,9 @@ func (c *TxClient) executeTransactionByTxType(txFn func(opts *bind.TransactOpts) spinner := ui.NewSpinner() spinner.Start("Submitting transaction...") - decodedTx, err := c.EthClient.Decode(txFn(c.EthClient.NewTXOpts())) + txOpts := c.EthClient.NewTXOpts() + txOpts.Context = ctx + decodedTx, err := c.EthClient.Decode(txFn(txOpts)) if err != nil { spinner.Stop() return TxOutput{Type: Regular}, err diff --git a/cmd/client/workflow_registry_v2_client.go b/cmd/client/workflow_registry_v2_client.go index a8dd6c5f..507885db 100644 --- a/cmd/client/workflow_registry_v2_client.go +++ b/cmd/client/workflow_registry_v2_client.go @@ -1,6 +1,7 @@ package client import ( + "context" "encoding/hex" "errors" "fmt" @@ -60,7 +61,19 @@ func NewWorkflowRegistryV2Client(logger *zerolog.Logger, ethClient *seth.Client, } } -func (wrc *WorkflowRegistryV2Client) LinkOwner(validityTimestamp *big.Int, proof [32]byte, signature []byte) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) callOpts(ctx context.Context) *bind.CallOpts { + opts := wrc.EthClient.NewCallOpts() + opts.Context = ctx + return opts +} + +func (wrc *WorkflowRegistryV2Client) txOpts(ctx context.Context) *bind.TransactOpts { + opts := wrc.EthClient.NewTXOpts() + opts.Context = ctx + return opts +} + +func (wrc *WorkflowRegistryV2Client) LinkOwner(ctx context.Context, validityTimestamp *big.Int, proof [32]byte, signature []byte) (*TxOutput, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -73,7 +86,7 @@ func (wrc *WorkflowRegistryV2Client) LinkOwner(validityTimestamp *big.Int, proof txFn := func(opts *bind.TransactOpts) (*types.Transaction, error) { return contract.LinkOwner(opts, validityTimestamp, proof, signature) } - txOut, err := wrc.executeTransactionByTxType(txFn, "LinkOwner", "OwnershipLinkUpdated", validityTimestamp, proof, signature) + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "LinkOwner", "OwnershipLinkUpdated", validityTimestamp, proof, signature) if err != nil { wrc.Logger.Error(). Str("contract", contract.Address().Hex()). @@ -92,7 +105,7 @@ func (wrc *WorkflowRegistryV2Client) LinkOwner(validityTimestamp *big.Int, proof return &txOut, nil } -func (wrc *WorkflowRegistryV2Client) UnlinkOwner(owner common.Address, validityTimestamp *big.Int, signature []byte) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) UnlinkOwner(ctx context.Context, owner common.Address, validityTimestamp *big.Int, signature []byte) (*TxOutput, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -105,7 +118,7 @@ func (wrc *WorkflowRegistryV2Client) UnlinkOwner(owner common.Address, validityT txFn := func(opts *bind.TransactOpts) (*types.Transaction, error) { return contract.UnlinkOwner(opts, owner, validityTimestamp, signature) } - txOut, err := wrc.executeTransactionByTxType(txFn, "UnlinkOwner", "OwnershipLinkUpdated", owner, validityTimestamp, signature) + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "UnlinkOwner", "OwnershipLinkUpdated", owner, validityTimestamp, signature) if err != nil { wrc.Logger.Error(). Str("contract", contract.Address().Hex()). @@ -124,7 +137,7 @@ func (wrc *WorkflowRegistryV2Client) UnlinkOwner(owner common.Address, validityT return &txOut, nil } -func (wrc *WorkflowRegistryV2Client) UpdateAllowedSigners(signers []common.Address, allowed bool) error { +func (wrc *WorkflowRegistryV2Client) UpdateAllowedSigners(ctx context.Context, signers []common.Address, allowed bool) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -135,7 +148,7 @@ func (wrc *WorkflowRegistryV2Client) UpdateAllowedSigners(signers []common.Addre } tx, err := wrc.EthClient.Decode( - contract.UpdateAllowedSigners(wrc.EthClient.NewTXOpts(), signers, allowed), + contract.UpdateAllowedSigners(wrc.txOpts(ctx), signers, allowed), ) if err != nil { wrc.Logger.Error(). @@ -162,7 +175,7 @@ func (wrc *WorkflowRegistryV2Client) UpdateAllowedSigners(signers []common.Addre return nil } -func (wrc *WorkflowRegistryV2Client) SetDonLimit(donFamily string, limit uint32, userDefaultLimit uint32) error { +func (wrc *WorkflowRegistryV2Client) SetDonLimit(ctx context.Context, donFamily string, limit uint32, userDefaultLimit uint32) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -173,7 +186,7 @@ func (wrc *WorkflowRegistryV2Client) SetDonLimit(donFamily string, limit uint32, } tx, err := wrc.EthClient.Decode( - contract.SetDONLimit(wrc.EthClient.NewTXOpts(), donFamily, limit, userDefaultLimit), + contract.SetDONLimit(wrc.txOpts(ctx), donFamily, limit, userDefaultLimit), ) if err != nil { wrc.Logger.Error(). @@ -196,7 +209,7 @@ func (wrc *WorkflowRegistryV2Client) SetDonLimit(donFamily string, limit uint32, return nil } -func (wrc *WorkflowRegistryV2Client) SetDONOverride(donFamily [32]byte, limit uint32, enabled bool) error { +func (wrc *WorkflowRegistryV2Client) SetDONOverride(ctx context.Context, donFamily [32]byte, limit uint32, enabled bool) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -207,7 +220,7 @@ func (wrc *WorkflowRegistryV2Client) SetDONOverride(donFamily [32]byte, limit ui } tx, err := wrc.EthClient.Decode( - contract.SetUserDONOverride(wrc.EthClient.NewTXOpts(), common.Address{}, common.Hash(donFamily).Hex(), limit, enabled), + contract.SetUserDONOverride(wrc.txOpts(ctx), common.Address{}, common.Hash(donFamily).Hex(), limit, enabled), ) if err != nil { wrc.Logger.Error(). @@ -230,7 +243,7 @@ func (wrc *WorkflowRegistryV2Client) SetDONOverride(donFamily [32]byte, limit ui return nil } -func (wrc *WorkflowRegistryV2Client) SetDefaults(maxPerDON, maxPerUserDON uint32) error { +func (wrc *WorkflowRegistryV2Client) SetDefaults(ctx context.Context, maxPerDON, maxPerUserDON uint32) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -261,7 +274,7 @@ func (wrc *WorkflowRegistryV2Client) SetDefaults(maxPerDON, maxPerUserDON uint32 return nil } -func (wrc *WorkflowRegistryV2Client) SetUserDONOverride(user common.Address, donFamily [32]byte, limit uint32, enabled bool) error { +func (wrc *WorkflowRegistryV2Client) SetUserDONOverride(ctx context.Context, user common.Address, donFamily [32]byte, limit uint32, enabled bool) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -272,7 +285,7 @@ func (wrc *WorkflowRegistryV2Client) SetUserDONOverride(user common.Address, don } tx, err := wrc.EthClient.Decode( - contract.SetUserDONOverride(wrc.EthClient.NewTXOpts(), user, common.Hash(donFamily).Hex(), limit, enabled), + contract.SetUserDONOverride(wrc.txOpts(ctx), user, common.Hash(donFamily).Hex(), limit, enabled), ) if err != nil { wrc.Logger.Error(). @@ -295,7 +308,7 @@ func (wrc *WorkflowRegistryV2Client) SetUserDONOverride(user common.Address, don return nil } -func (wrc *WorkflowRegistryV2Client) CanLinkOwner(owner common.Address, validityTimestamp *big.Int, proof [32]byte, signature []byte) error { +func (wrc *WorkflowRegistryV2Client) CanLinkOwner(ctx context.Context, owner common.Address, validityTimestamp *big.Int, proof [32]byte, signature []byte) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -305,7 +318,7 @@ func (wrc *WorkflowRegistryV2Client) CanLinkOwner(owner common.Address, validity } _, err = callContractMethodV2(wrc, func() (struct{}, error) { - return struct{}{}, contract.CanLinkOwner(wrc.EthClient.NewCallOpts(), owner, validityTimestamp, proof, signature) + return struct{}{}, contract.CanLinkOwner(wrc.callOpts(ctx), owner, validityTimestamp, proof, signature) }) if err != nil { wrc.Logger.Error(). @@ -322,7 +335,7 @@ func (wrc *WorkflowRegistryV2Client) CanLinkOwner(owner common.Address, validity return nil } -func (wrc *WorkflowRegistryV2Client) CanUnlinkOwner(owner common.Address, validityTimestamp *big.Int, signature []byte) error { +func (wrc *WorkflowRegistryV2Client) CanUnlinkOwner(ctx context.Context, owner common.Address, validityTimestamp *big.Int, signature []byte) error { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -332,7 +345,7 @@ func (wrc *WorkflowRegistryV2Client) CanUnlinkOwner(owner common.Address, validi } _, err = callContractMethodV2(wrc, func() (struct{}, error) { - return struct{}{}, contract.CanUnlinkOwner(wrc.EthClient.NewCallOpts(), owner, validityTimestamp, signature) + return struct{}{}, contract.CanUnlinkOwner(wrc.callOpts(ctx), owner, validityTimestamp, signature) }) if err != nil { wrc.Logger.Error(). @@ -349,72 +362,72 @@ func (wrc *WorkflowRegistryV2Client) CanUnlinkOwner(owner common.Address, validi return nil } -func (wrc *WorkflowRegistryV2Client) GetLinkedOwners(start, batchSize *big.Int) ([]common.Address, error) { +func (wrc *WorkflowRegistryV2Client) GetLinkedOwners(ctx context.Context, start, batchSize *big.Int) ([]common.Address, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetLinkedOwners") return nil, err } - addrs, err := contract.GetLinkedOwners(wrc.EthClient.NewCallOpts(), start, batchSize) + addrs, err := contract.GetLinkedOwners(wrc.callOpts(ctx), start, batchSize) if err != nil { wrc.Logger.Error().Err(err).Msg("GetLinkedOwners call failed") } return addrs, err } -func (wrc *WorkflowRegistryV2Client) GetMaxWorkflowsPerDON(donFamily [32]byte) (uint32, error) { +func (wrc *WorkflowRegistryV2Client) GetMaxWorkflowsPerDON(ctx context.Context, donFamily [32]byte) (uint32, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetMaxWorkflowsPerDON") return 0, err } - val, err := contract.GetMaxWorkflowsPerDON(wrc.EthClient.NewCallOpts(), common.Hash(donFamily).Hex()) + val, err := contract.GetMaxWorkflowsPerDON(wrc.callOpts(ctx), common.Hash(donFamily).Hex()) if err != nil { wrc.Logger.Error().Err(err).Msg("GetMaxWorkflowsPerDON call failed") } return val.MaxWorkflows, err } -func (wrc *WorkflowRegistryV2Client) GetMaxWorkflowsPerUserDON(user common.Address, donFamily [32]byte) (uint32, error) { +func (wrc *WorkflowRegistryV2Client) GetMaxWorkflowsPerUserDON(ctx context.Context, user common.Address, donFamily [32]byte) (uint32, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetMaxWorkflowsPerUserDON") return 0, err } - val, err := contract.GetMaxWorkflowsPerUserDON(wrc.EthClient.NewCallOpts(), user, common.Hash(donFamily).Hex()) + val, err := contract.GetMaxWorkflowsPerUserDON(wrc.callOpts(ctx), user, common.Hash(donFamily).Hex()) if err != nil { wrc.Logger.Error().Err(err).Msg("GetMaxWorkflowsPerUserDON call failed") } return val, err } -func (wrc *WorkflowRegistryV2Client) GetMaxWorkflowsPerUserDONByFamily(user common.Address, donFamily string) (uint32, error) { +func (wrc *WorkflowRegistryV2Client) GetMaxWorkflowsPerUserDONByFamily(ctx context.Context, user common.Address, donFamily string) (uint32, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetMaxWorkflowsPerUserDONByFamily") return 0, err } - val, err := contract.GetMaxWorkflowsPerUserDON(wrc.EthClient.NewCallOpts(), user, donFamily) + val, err := contract.GetMaxWorkflowsPerUserDON(wrc.callOpts(ctx), user, donFamily) if err != nil { wrc.Logger.Error().Err(err).Msg("GetMaxWorkflowsPerUserDONByFamily call failed") } return val, err } -func (wrc *WorkflowRegistryV2Client) IsAllowedSigner(signer common.Address) (bool, error) { +func (wrc *WorkflowRegistryV2Client) IsAllowedSigner(ctx context.Context, signer common.Address) (bool, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for IsAllowedSigner") return false, err } - ok, err := contract.IsAllowedSigner(wrc.EthClient.NewCallOpts(), signer) + ok, err := contract.IsAllowedSigner(wrc.callOpts(ctx), signer) if err != nil { wrc.Logger.Error().Err(err).Msg("IsAllowedSigner call failed") } return ok, err } -func (wrc *WorkflowRegistryV2Client) IsOwnerLinked(owner common.Address) (bool, error) { +func (wrc *WorkflowRegistryV2Client) IsOwnerLinked(ctx context.Context, owner common.Address) (bool, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -424,7 +437,7 @@ func (wrc *WorkflowRegistryV2Client) IsOwnerLinked(owner common.Address) (bool, } result, err := callContractMethodV2(wrc, func() (bool, error) { - return contract.IsOwnerLinked(wrc.EthClient.NewCallOpts(), owner) + return contract.IsOwnerLinked(wrc.callOpts(ctx), owner) }) if err != nil { wrc.Logger.Error(). @@ -442,33 +455,33 @@ func (wrc *WorkflowRegistryV2Client) IsOwnerLinked(owner common.Address) (bool, return result, nil } -func (wrc *WorkflowRegistryV2Client) TotalLinkedOwners() (*big.Int, error) { +func (wrc *WorkflowRegistryV2Client) TotalLinkedOwners(ctx context.Context) (*big.Int, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for TotalLinkedOwners") return nil, err } - total, err := contract.TotalLinkedOwners(wrc.EthClient.NewCallOpts()) + total, err := contract.TotalLinkedOwners(wrc.callOpts(ctx)) if err != nil { wrc.Logger.Error().Err(err).Msg("TotalLinkedOwners call failed") } return total, err } -func (wrc *WorkflowRegistryV2Client) TypeAndVersion() (string, error) { +func (wrc *WorkflowRegistryV2Client) TypeAndVersion(ctx context.Context) (string, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for TypeAndVersion") return "", err } - tv, err := contract.TypeAndVersion(wrc.EthClient.NewCallOpts()) + tv, err := contract.TypeAndVersion(wrc.callOpts(ctx)) if err != nil { wrc.Logger.Error().Err(err).Msg("TypeAndVersion call failed") } return tv, err } -func (wrc *WorkflowRegistryV2Client) UpsertWorkflow(params RegisterWorkflowV2Parameters) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) UpsertWorkflow(ctx context.Context, params RegisterWorkflowV2Parameters) (*TxOutput, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -492,7 +505,7 @@ func (wrc *WorkflowRegistryV2Client) UpsertWorkflow(params RegisterWorkflowV2Par params.KeepAlive, ) } - txOut, err := wrc.executeTransactionByTxType(txFn, "UpsertWorkflow", "WorkflowRegistered|WorkflowUpdated", + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "UpsertWorkflow", "WorkflowRegistered|WorkflowUpdated", params.WorkflowName, params.Tag, params.WorkflowID, @@ -513,7 +526,7 @@ func (wrc *WorkflowRegistryV2Client) UpsertWorkflow(params RegisterWorkflowV2Par return &txOut, nil } -func (wrc *WorkflowRegistryV2Client) GetWorkflow(owner common.Address, workflowName, tag string) (workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { +func (wrc *WorkflowRegistryV2Client) GetWorkflow(ctx context.Context, owner common.Address, workflowName, tag string) (workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetWorkflow") @@ -521,7 +534,7 @@ func (wrc *WorkflowRegistryV2Client) GetWorkflow(owner common.Address, workflowN } result, err := callContractMethodV2(wrc, func() (workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { - return contract.GetWorkflow(wrc.EthClient.NewCallOpts(), owner, workflowName, tag) + return contract.GetWorkflow(wrc.callOpts(ctx), owner, workflowName, tag) }) if err != nil { wrc.Logger.Error().Err(err).Msg("GetWorkflow call failed") @@ -529,7 +542,7 @@ func (wrc *WorkflowRegistryV2Client) GetWorkflow(owner common.Address, workflowN return result, err } -func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwnerAndName(owner common.Address, workflowName string, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { +func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwnerAndName(ctx context.Context, owner common.Address, workflowName string, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetWorkflowListByOwnerAndName") @@ -537,7 +550,7 @@ func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwnerAndName(owner common. } result, err := callContractMethodV2(wrc, func() ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { - return contract.GetWorkflowListByOwnerAndName(wrc.EthClient.NewCallOpts(), owner, workflowName, start, limit) + return contract.GetWorkflowListByOwnerAndName(wrc.callOpts(ctx), owner, workflowName, start, limit) }) if err != nil { wrc.Logger.Error().Err(err).Msg("GetWorkflowListByOwnerAndName call failed") @@ -545,7 +558,7 @@ func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwnerAndName(owner common. return result, err } -func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwner(owner common.Address, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { +func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwner(ctx context.Context, owner common.Address, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error().Err(err).Msg("Failed to connect for GetWorkflowListByOwner") @@ -553,7 +566,7 @@ func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwner(owner common.Address } result, err := callContractMethodV2(wrc, func() ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { - return contract.GetWorkflowListByOwner(wrc.EthClient.NewCallOpts(), owner, start, limit) + return contract.GetWorkflowListByOwner(wrc.callOpts(ctx), owner, start, limit) }) if err != nil { wrc.Logger.Error().Err(err).Msg("GetWorkflowListByOwner call failed") @@ -562,6 +575,7 @@ func (wrc *WorkflowRegistryV2Client) GetWorkflowListByOwner(owner common.Address } func (wrc *WorkflowRegistryV2Client) CheckUserDonLimit( + ctx context.Context, owner common.Address, donFamily string, pending uint32, @@ -569,7 +583,7 @@ func (wrc *WorkflowRegistryV2Client) CheckUserDonLimit( const workflowStatusActive = uint8(0) const workflowListPageSize = int64(200) - maxAllowed, err := wrc.GetMaxWorkflowsPerUserDONByFamily(owner, donFamily) + maxAllowed, err := wrc.GetMaxWorkflowsPerUserDONByFamily(ctx, owner, donFamily) if err != nil { return fmt.Errorf("failed to fetch per-user workflow limit: %w", err) } @@ -579,7 +593,7 @@ func (wrc *WorkflowRegistryV2Client) CheckUserDonLimit( limit := big.NewInt(workflowListPageSize) for { - list, err := wrc.GetWorkflowListByOwner(owner, start, limit) + list, err := wrc.GetWorkflowListByOwner(ctx, owner, start, limit) if err != nil { return fmt.Errorf("failed to check active workflows for DON %s: %w", donFamily, err) } @@ -606,7 +620,7 @@ func (wrc *WorkflowRegistryV2Client) CheckUserDonLimit( return nil } -func (wrc *WorkflowRegistryV2Client) DeleteWorkflow(workflowID [32]byte) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) DeleteWorkflow(ctx context.Context, workflowID [32]byte) (*TxOutput, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -619,7 +633,7 @@ func (wrc *WorkflowRegistryV2Client) DeleteWorkflow(workflowID [32]byte) (*TxOut txFn := func(opts *bind.TransactOpts) (*types.Transaction, error) { return contract.DeleteWorkflow(opts, workflowID) } - txOut, err := wrc.executeTransactionByTxType(txFn, "DeleteWorkflow", "WorkflowDeleted", workflowID) + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "DeleteWorkflow", "WorkflowDeleted", workflowID) if err != nil { wrc.Logger.Error(). Str("contract", contract.Address().Hex()). @@ -630,7 +644,7 @@ func (wrc *WorkflowRegistryV2Client) DeleteWorkflow(workflowID [32]byte) (*TxOut return &txOut, nil } -func (wrc *WorkflowRegistryV2Client) BatchPauseWorkflows(workflowIDs [][32]byte) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) BatchPauseWorkflows(ctx context.Context, workflowIDs [][32]byte) (*TxOutput, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -646,7 +660,7 @@ func (wrc *WorkflowRegistryV2Client) BatchPauseWorkflows(workflowIDs [][32]byte) workflowIDs, ) } - txOut, err := wrc.executeTransactionByTxType(txFn, "BatchPauseWorkflows", "WorkflowStatusUpdated", workflowIDs) + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "BatchPauseWorkflows", "WorkflowStatusUpdated", workflowIDs) if err != nil { wrc.Logger.Error(). Str("contract", contract.Address().Hex()). @@ -657,7 +671,7 @@ func (wrc *WorkflowRegistryV2Client) BatchPauseWorkflows(workflowIDs [][32]byte) return &txOut, nil } -func (wrc *WorkflowRegistryV2Client) ActivateWorkflow(workflowID [32]byte, donFamily string) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) ActivateWorkflow(ctx context.Context, workflowID [32]byte, donFamily string) (*TxOutput, error) { contract, err := workflow_registry_v2_wrapper.NewWorkflowRegistry(wrc.ContractAddress, wrc.EthClient.Client) if err != nil { wrc.Logger.Error(). @@ -670,7 +684,7 @@ func (wrc *WorkflowRegistryV2Client) ActivateWorkflow(workflowID [32]byte, donFa txFn := func(opts *bind.TransactOpts) (*types.Transaction, error) { return contract.ActivateWorkflow(opts, workflowID, donFamily) } - txOut, err := wrc.executeTransactionByTxType(txFn, "ActivateWorkflow", "WorkflowActivated", workflowID, donFamily) + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "ActivateWorkflow", "WorkflowActivated", workflowID, donFamily) if err != nil { wrc.Logger.Error(). Str("contract", contract.Address().Hex()). @@ -715,7 +729,7 @@ func (wrc *WorkflowRegistryV2Client) validateReceiptAndEvent( // IsRequestAllowlisted queries the registry to check if a given (owner, requestDigest) is allowlisted. // requestDigestHex may include or omit the 0x prefix. -func (wrc *WorkflowRegistryV2Client) IsRequestAllowlisted(owner common.Address, digest [32]byte) (bool, error) { +func (wrc *WorkflowRegistryV2Client) IsRequestAllowlisted(ctx context.Context, owner common.Address, digest [32]byte) (bool, error) { var contract workflowRegistryV2Contract if wrc.Wr != nil { contract = wrc.Wr @@ -731,7 +745,7 @@ func (wrc *WorkflowRegistryV2Client) IsRequestAllowlisted(owner common.Address, var allowlisted bool _, err := callContractMethodV2(wrc, func() (string, error) { var callErr error - allowlisted, callErr = contract.IsRequestAllowlisted(wrc.EthClient.NewCallOpts(), owner, digest) + allowlisted, callErr = contract.IsRequestAllowlisted(wrc.callOpts(ctx), owner, digest) return "", callErr }) if err != nil { @@ -753,7 +767,7 @@ func (wrc *WorkflowRegistryV2Client) IsRequestAllowlisted(owner common.Address, // AllowlistRequest sends the request digest to the WorkflowRegistry allowlist with a default expiry of now + 10 minutes. // `requestDigestHex` should be the hex string produced by utils.CalculateRequestDigest(...), with or without "0x". -func (wrc *WorkflowRegistryV2Client) AllowlistRequest(requestDigest [32]byte, duration time.Duration) (*TxOutput, error) { +func (wrc *WorkflowRegistryV2Client) AllowlistRequest(ctx context.Context, requestDigest [32]byte, duration time.Duration) (*TxOutput, error) { var contract workflowRegistryV2Contract if wrc.Wr != nil { contract = wrc.Wr @@ -772,7 +786,7 @@ func (wrc *WorkflowRegistryV2Client) AllowlistRequest(requestDigest [32]byte, du txFn := func(opts *bind.TransactOpts) (*types.Transaction, error) { return contract.AllowlistRequest(opts, requestDigest, deadline) } - txOut, err := wrc.executeTransactionByTxType(txFn, "AllowlistRequest", "RequestAllowlisted", requestDigest, duration) + txOut, err := wrc.executeTransactionByTxType(ctx, txFn, "AllowlistRequest", "RequestAllowlisted", requestDigest, duration) if err != nil { wrc.Logger.Error(). Str("contract", wrc.ContractAddress.Hex()). diff --git a/cmd/client/workflow_registry_v2_client_test.go b/cmd/client/workflow_registry_v2_client_test.go index fbda002c..967cbe6f 100644 --- a/cmd/client/workflow_registry_v2_client_test.go +++ b/cmd/client/workflow_registry_v2_client_test.go @@ -1,6 +1,7 @@ package client import ( + "context" "errors" "testing" @@ -59,7 +60,7 @@ func TestIsRequestAllowlisted_Success(t *testing.T) { reqDigest, ).Return(true, nil).Once() - ok, err := wrc.IsRequestAllowlisted(owner, reqDigest) + ok, err := wrc.IsRequestAllowlisted(context.Background(), owner, reqDigest) assert.NoError(t, err) assert.True(t, ok) @@ -81,7 +82,7 @@ func TestIsRequestAllowlisted_ContractError(t *testing.T) { reqDigest, ).Return(false, errors.New("revert: not allowed")).Once() - ok, err := wrc.IsRequestAllowlisted(owner, reqDigest) + ok, err := wrc.IsRequestAllowlisted(context.Background(), owner, reqDigest) assert.Error(t, err) assert.Contains(t, err.Error(), "not allowed") assert.False(t, ok) diff --git a/cmd/secrets/common/handler.go b/cmd/secrets/common/handler.go index 12ff42eb..36f81ea6 100644 --- a/cmd/secrets/common/handler.go +++ b/cmd/secrets/common/handler.go @@ -68,13 +68,14 @@ type Handler struct { Wrc *client.WorkflowRegistryV2Client Credentials *credentials.Credentials Settings *settings.Settings + execCtx context.Context } // NewHandler creates a new handler instance. // secretsAuth is the value of the --secrets-auth flag (e.g. "onchain" or "browser"). // For the browser OAuth flow the on-chain WorkflowRegistryV2Client is not needed and is // intentionally skipped to avoid requiring an ethereum-mainnet RPC URL. -func NewHandler(ctx *runtime.Context, secretsFilePath, secretsAuth string) (*Handler, error) { +func NewHandler(execCtx context.Context, ctx *runtime.Context, secretsFilePath, secretsAuth string) (*Handler, error) { var pk *ecdsa.PrivateKey var err error if ctx.Settings.User.EthPrivateKey != "" { @@ -97,11 +98,12 @@ func NewHandler(ctx *runtime.Context, secretsFilePath, secretsAuth string) (*Han EnvironmentSet: ctx.EnvironmentSet, Credentials: ctx.Credentials, Settings: ctx.Settings, + execCtx: execCtx, } h.Gw = &HTTPClient{URL: h.EnvironmentSet.GatewayURL, Client: &http.Client{Timeout: 90 * time.Second}} if !IsBrowserFlow(secretsAuth) { - wrc, err := h.ClientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.ClientFactory.NewWorkflowRegistryV2Client(execCtx) if err != nil { return nil, fmt.Errorf("failed to create workflow registry client: %w", err) } @@ -402,13 +404,15 @@ func HexToBytes32(h string) ([32]byte, error) { // Execute implements secrets create and update from YAML (multisig bundle, owner-key with allowlist, or interactive org sign-in). func (h *Handler) Execute( + ctx context.Context, inputs UpsertSecretsInputs, method string, duration time.Duration, secretsAuth string, ) error { + h.execCtx = ctx if IsBrowserFlow(secretsAuth) { - return h.executeBrowserUpsert(context.Background(), inputs, method) + return h.executeBrowserUpsert(ctx, inputs, method) } if err := h.EnsureDeploymentRPCForOwnerKeySecrets(); err != nil { @@ -416,7 +420,7 @@ func (h *Handler) Execute( } ui.Dim("Verifying ownership...") - if err := h.EnsureOwnerLinkedOrFail(); err != nil { + if err := h.EnsureOwnerLinkedOrFail(ctx); err != nil { return err } @@ -478,13 +482,13 @@ func (h *Handler) Execute( ownerAddr := common.HexToAddress(owner) - allowlisted, err := h.Wrc.IsRequestAllowlisted(ownerAddr, digest) + allowlisted, err := h.Wrc.IsRequestAllowlisted(ctx, ownerAddr, digest) if err != nil { return fmt.Errorf("allowlist check failed: %w", err) } var txOut *client.TxOutput if !allowlisted { - if txOut, err = h.Wrc.AllowlistRequest(digest, duration); err != nil { + if txOut, err = h.Wrc.AllowlistRequest(ctx, digest, duration); err != nil { return fmt.Errorf("allowlist request failed: %w", err) } } @@ -691,13 +695,13 @@ func (h *Handler) ParseVaultGatewayResponse(method string, respBody []byte) erro } // EnsureOwnerLinkedOrFail TODO this reuses the same logic as in auto_link.go which is tied to deploy; consider refactoring to avoid duplication -func (h *Handler) EnsureOwnerLinkedOrFail() error { +func (h *Handler) EnsureOwnerLinkedOrFail(ctx context.Context) error { if !common.IsHexAddress(h.OwnerAddress) { return fmt.Errorf("owner address %q is not a valid hex EVM address; check your workflow settings", h.OwnerAddress) } ownerAddr := common.HexToAddress(h.OwnerAddress) - linked, err := h.Wrc.IsOwnerLinked(ownerAddr) + linked, err := h.Wrc.IsOwnerLinked(ctx, ownerAddr) if err != nil { return fmt.Errorf("failed to check owner link status: %w", err) } diff --git a/cmd/secrets/common/handler_test.go b/cmd/secrets/common/handler_test.go index cd58c70f..4a2d14b0 100644 --- a/cmd/secrets/common/handler_test.go +++ b/cmd/secrets/common/handler_test.go @@ -2,6 +2,7 @@ package common import ( "bytes" + "context" "crypto/rand" "encoding/hex" "encoding/json" @@ -14,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/rs/zerolog" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" vaultcommon "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" @@ -315,7 +317,7 @@ func TestNewHandler_WorkflowRegistryClient(t *testing.T) { t.Run("browser flow: WorkflowRegistryV2Client is not created", func(t *testing.T) { ctx, cf := newCtx(t) - h, err := NewHandler(ctx, "", SecretsAuthBrowser) + h, err := NewHandler(context.Background(), ctx, "", SecretsAuthBrowser) require.NoError(t, err) require.Nil(t, h.Wrc, "Wrc must be nil for browser flow") cf.AssertNotCalled(t, "NewWorkflowRegistryV2Client") @@ -323,18 +325,18 @@ func TestNewHandler_WorkflowRegistryClient(t *testing.T) { t.Run("owner-key flow: WorkflowRegistryV2Client is created", func(t *testing.T) { ctx, cf := newCtx(t) - cf.On("NewWorkflowRegistryV2Client").Return(nil, nil) - h, err := NewHandler(ctx, "", SecretsAuthOnchain) + cf.On("NewWorkflowRegistryV2Client", mock.Anything).Return(nil, nil) + h, err := NewHandler(context.Background(), ctx, "", SecretsAuthOnchain) require.NoError(t, err) // Wrc may be nil if the mock returns nil, but the factory must have been called. _ = h - cf.AssertCalled(t, "NewWorkflowRegistryV2Client") + cf.AssertCalled(t, "NewWorkflowRegistryV2Client", mock.Anything) }) t.Run("owner-key flow: factory error is propagated", func(t *testing.T) { ctx, cf := newCtx(t) - cf.On("NewWorkflowRegistryV2Client").Return(nil, errors.New("rpc url not found for chain ethereum-mainnet")) - _, err := NewHandler(ctx, "", SecretsAuthOnchain) + cf.On("NewWorkflowRegistryV2Client", mock.Anything).Return(nil, errors.New("rpc url not found for chain ethereum-mainnet")) + _, err := NewHandler(context.Background(), ctx, "", SecretsAuthOnchain) require.Error(t, err) require.Contains(t, err.Error(), "workflow registry client") }) diff --git a/cmd/secrets/common/test_helpers.go b/cmd/secrets/common/test_helpers.go index 648f6df4..b79ddf55 100644 --- a/cmd/secrets/common/test_helpers.go +++ b/cmd/secrets/common/test_helpers.go @@ -2,6 +2,7 @@ package common import ( "bytes" + "context" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" @@ -43,8 +44,8 @@ func (m *MockClientFactory) GetSkipConfirmation() bool { panic("not used in these tests") } -func (m *MockClientFactory) NewWorkflowRegistryV2Client() (*client.WorkflowRegistryV2Client, error) { - args := m.Called() +func (m *MockClientFactory) NewWorkflowRegistryV2Client(ctx context.Context) (*client.WorkflowRegistryV2Client, error) { + args := m.Called(ctx) var c *client.WorkflowRegistryV2Client if v := args.Get(0); v != nil { c = v.(*client.WorkflowRegistryV2Client) diff --git a/cmd/secrets/create/create.go b/cmd/secrets/create/create.go index 4b25d3df..8209b103 100644 --- a/cmd/secrets/create/create.go +++ b/cmd/secrets/create/create.go @@ -41,7 +41,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - h, err := common.NewHandler(ctx, secretsFilePath, secretsAuth) + h, err := common.NewHandler(cmd.Context(), ctx, secretsFilePath, secretsAuth) if err != nil { return err } @@ -71,7 +71,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - return h.Execute(inputs, vaulttypes.MethodSecretsCreate, duration, secretsAuth) + return h.Execute(cmd.Context(), inputs, vaulttypes.MethodSecretsCreate, duration, secretsAuth) }, } diff --git a/cmd/secrets/delete/delete.go b/cmd/secrets/delete/delete.go index e691971a..57126591 100644 --- a/cmd/secrets/delete/delete.go +++ b/cmd/secrets/delete/delete.go @@ -74,7 +74,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - h, err := common.NewHandler(ctx, secretsFilePath, secretsAuth) + h, err := common.NewHandler(cmd.Context(), ctx, secretsFilePath, secretsAuth) if err != nil { return err } @@ -103,7 +103,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - return Execute(h, inputs, duration, secretsAuth) + return Execute(cmd.Context(), h, inputs, duration, secretsAuth) }, } @@ -116,14 +116,14 @@ func New(ctx *runtime.Context) *cobra.Command { // Two paths: // - MSIG step 1: build request, compute digest, write bundle, print steps // - EOA: allowlist if needed, then POST to gateway -func Execute(h *common.Handler, inputs DeleteSecretsInputs, duration time.Duration, secretsAuth string) error { +func Execute(ctx context.Context, h *common.Handler, inputs DeleteSecretsInputs, duration time.Duration, secretsAuth string) error { if !common.IsBrowserFlow(secretsAuth) { if err := h.EnsureDeploymentRPCForOwnerKeySecrets(); err != nil { return err } spinner := ui.NewSpinner() spinner.Start("Verifying ownership...") - if err := h.EnsureOwnerLinkedOrFail(); err != nil { + if err := h.EnsureOwnerLinkedOrFail(ctx); err != nil { spinner.Stop() return err } @@ -187,13 +187,13 @@ func Execute(h *common.Handler, inputs DeleteSecretsInputs, duration time.Durati ownerAddr := ethcommon.HexToAddress(owner) - allowlisted, err := h.Wrc.IsRequestAllowlisted(ownerAddr, digest) + allowlisted, err := h.Wrc.IsRequestAllowlisted(ctx, ownerAddr, digest) if err != nil { return fmt.Errorf("allowlist check failed: %w", err) } var txOut *client.TxOutput if !allowlisted { - if txOut, err = h.Wrc.AllowlistRequest(digest, duration); err != nil { + if txOut, err = h.Wrc.AllowlistRequest(ctx, digest, duration); err != nil { return fmt.Errorf("allowlist request failed: %w", err) } } else { diff --git a/cmd/secrets/execute/execute.go b/cmd/secrets/execute/execute.go index f83a803e..8c89f303 100644 --- a/cmd/secrets/execute/execute.go +++ b/cmd/secrets/execute/execute.go @@ -37,7 +37,7 @@ func New(ctx *runtime.Context) *cobra.Command { return fmt.Errorf("execute expects a bundle .json file; got %q", ext) } - h, err := common.NewHandler(ctx, bundlePath, common.SecretsAuthOnchain) + h, err := common.NewHandler(cmd.Context(), ctx, bundlePath, common.SecretsAuthOnchain) if err != nil { return err } @@ -71,7 +71,7 @@ func New(ctx *runtime.Context) *cobra.Command { ownerAddr := ethcommon.HexToAddress(h.OwnerAddress) - allowlisted, err := h.Wrc.IsRequestAllowlisted(ownerAddr, digest) + allowlisted, err := h.Wrc.IsRequestAllowlisted(cmd.Context(), ownerAddr, digest) if err != nil { return fmt.Errorf("allowlist check failed: %w", err) } diff --git a/cmd/secrets/list/list.go b/cmd/secrets/list/list.go index 03f8adf0..6a4a58b8 100644 --- a/cmd/secrets/list/list.go +++ b/cmd/secrets/list/list.go @@ -52,7 +52,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - h, err := common.NewHandler(ctx, "", secretsAuth) + h, err := common.NewHandler(cmd.Context(), ctx, "", secretsAuth) if err != nil { return err } @@ -74,7 +74,7 @@ func New(ctx *runtime.Context) *cobra.Command { return fmt.Errorf("invalid --timeout: must be greater than 0 and less than %dh (%dd)", maxHours, maxDays) } - return Execute(h, namespace, duration, secretsAuth) + return Execute(cmd.Context(), h, namespace, duration, secretsAuth) }, } @@ -86,14 +86,14 @@ func New(ctx *runtime.Context) *cobra.Command { } // Execute performs: build request → (MSIG step 1 bundle OR EOA allowlist+post) → parse. -func Execute(h *common.Handler, namespace string, duration time.Duration, secretsAuth string) error { +func Execute(ctx context.Context, h *common.Handler, namespace string, duration time.Duration, secretsAuth string) error { if !common.IsBrowserFlow(secretsAuth) { if err := h.EnsureDeploymentRPCForOwnerKeySecrets(); err != nil { return err } spinner := ui.NewSpinner() spinner.Start("Verifying ownership...") - if err := h.EnsureOwnerLinkedOrFail(); err != nil { + if err := h.EnsureOwnerLinkedOrFail(ctx); err != nil { spinner.Stop() return err } @@ -140,13 +140,13 @@ func Execute(h *common.Handler, namespace string, duration time.Duration, secret ownerAddr := ethcommon.HexToAddress(owner) - allowlisted, err := h.Wrc.IsRequestAllowlisted(ownerAddr, digest) + allowlisted, err := h.Wrc.IsRequestAllowlisted(ctx, ownerAddr, digest) if err != nil { return fmt.Errorf("allowlist check failed: %w", err) } var txOut *client.TxOutput if !allowlisted { - if txOut, err = h.Wrc.AllowlistRequest(digest, duration); err != nil { + if txOut, err = h.Wrc.AllowlistRequest(ctx, digest, duration); err != nil { return fmt.Errorf("allowlist request failed: %w", err) } } diff --git a/cmd/secrets/update/update.go b/cmd/secrets/update/update.go index 24a1b0cd..a7bc84ef 100644 --- a/cmd/secrets/update/update.go +++ b/cmd/secrets/update/update.go @@ -41,7 +41,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - h, err := common.NewHandler(ctx, secretsFilePath, secretsAuth) + h, err := common.NewHandler(cmd.Context(), ctx, secretsFilePath, secretsAuth) if err != nil { return err } @@ -72,7 +72,7 @@ func New(ctx *runtime.Context) *cobra.Command { return err } - return h.Execute(inputs, vaulttypes.MethodSecretsUpdate, duration, secretsAuth) + return h.Execute(cmd.Context(), inputs, vaulttypes.MethodSecretsUpdate, duration, secretsAuth) }, } diff --git a/cmd/workflow/activate/registry_activate_strategy_onchain.go b/cmd/workflow/activate/registry_activate_strategy_onchain.go index a6878606..6a9f9919 100644 --- a/cmd/workflow/activate/registry_activate_strategy_onchain.go +++ b/cmd/workflow/activate/registry_activate_strategy_onchain.go @@ -35,7 +35,7 @@ func newOnchainRegistryActivateStrategy(h *handler) (*onchainRegistryActivateStr a.wg.Add(1) go func() { defer a.wg.Done() - wrc, err := h.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.clientFactory.NewWorkflowRegistryV2Client(h.execCtx) if err != nil { a.initErr = fmt.Errorf("failed to create workflow registry client: %w", err) return @@ -58,7 +58,7 @@ func (a *onchainRegistryActivateStrategy) Activate() error { ownerAddr := common.HexToAddress(workflowOwner) - workflows, err := workflowcommon.FetchAllWorkflowsByOwnerAndName(a.wrc, ownerAddr, workflowName) + workflows, err := workflowcommon.FetchAllWorkflowsByOwnerAndName(h.execCtx, a.wrc, ownerAddr, workflowName) if err != nil { return fmt.Errorf("failed to get workflow list: %w", err) } @@ -80,13 +80,13 @@ func (a *onchainRegistryActivateStrategy) Activate() error { return fmt.Errorf("workflow is already active, cancelling transaction") } - if err := a.wrc.CheckUserDonLimit(ownerAddr, h.inputs.DonFamily, 1); err != nil { + if err := a.wrc.CheckUserDonLimit(h.execCtx, ownerAddr, h.inputs.DonFamily, 1); err != nil { return err } ui.Dim(fmt.Sprintf("Activating workflow: Name=%s, Owner=%s, WorkflowID=%s", workflowName, workflowOwner, hex.EncodeToString(latest.WorkflowId[:]))) - txOut, err := a.wrc.ActivateWorkflow(latest.WorkflowId, h.inputs.DonFamily) + txOut, err := a.wrc.ActivateWorkflow(h.execCtx, latest.WorkflowId, h.inputs.DonFamily) if err != nil { return fmt.Errorf("failed to activate workflow: %w", err) } diff --git a/cmd/workflow/common/workflow_list.go b/cmd/workflow/common/workflow_list.go index f51d9485..848945b0 100644 --- a/cmd/workflow/common/workflow_list.go +++ b/cmd/workflow/common/workflow_list.go @@ -1,6 +1,7 @@ package common import ( + "context" "math/big" "github.com/ethereum/go-ethereum/common" @@ -12,11 +13,12 @@ const workflowListPageSize = int64(200) // WorkflowListByOwnerAndNameClient fetches workflow metadata pages from the registry. type WorkflowListByOwnerAndNameClient interface { - GetWorkflowListByOwnerAndName(owner common.Address, workflowName string, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) + GetWorkflowListByOwnerAndName(ctx context.Context, owner common.Address, workflowName string, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) } // FetchAllWorkflowsByOwnerAndName returns every workflow version for owner+name, paginating until exhausted. func FetchAllWorkflowsByOwnerAndName( + ctx context.Context, wrc WorkflowListByOwnerAndNameClient, owner common.Address, name string, @@ -28,7 +30,7 @@ func FetchAllWorkflowsByOwnerAndName( ) for { - list, err := wrc.GetWorkflowListByOwnerAndName(owner, name, start, limit) + list, err := wrc.GetWorkflowListByOwnerAndName(ctx, owner, name, start, limit) if err != nil { return nil, err } diff --git a/cmd/workflow/delete/registry_delete_strategy_onchain.go b/cmd/workflow/delete/registry_delete_strategy_onchain.go index 5cd3a9b5..58f93dcf 100644 --- a/cmd/workflow/delete/registry_delete_strategy_onchain.go +++ b/cmd/workflow/delete/registry_delete_strategy_onchain.go @@ -35,7 +35,7 @@ func newOnchainRegistryDeleteStrategy(h *handler) (*onchainRegistryDeleteStrateg a.wg.Add(1) go func() { defer a.wg.Done() - wrc, err := h.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.clientFactory.NewWorkflowRegistryV2Client(h.execCtx) if err != nil { a.initErr = fmt.Errorf("failed to create workflow registry client: %w", err) return @@ -56,7 +56,7 @@ func (a *onchainRegistryDeleteStrategy) FetchWorkflows() ([]WorkflowToDelete, er workflowName := h.inputs.WorkflowName workflowOwner := common.HexToAddress(h.inputs.WorkflowOwner) - allWorkflows, err := workflowcommon.FetchAllWorkflowsByOwnerAndName(a.wrc, workflowOwner, workflowName) + allWorkflows, err := workflowcommon.FetchAllWorkflowsByOwnerAndName(h.execCtx, a.wrc, workflowOwner, workflowName) if err != nil { return nil, fmt.Errorf("failed to get workflow list: %w", err) } @@ -83,7 +83,7 @@ func (a *onchainRegistryDeleteStrategy) DeleteWorkflows(workflows []WorkflowToDe var errs []error for _, wf := range workflows { workflowID := wf.RawID.([32]byte) - txOut, err := a.wrc.DeleteWorkflow(workflowID) + txOut, err := a.wrc.DeleteWorkflow(h.execCtx, workflowID) if err != nil { h.log.Error(). Err(err). diff --git a/cmd/workflow/deploy/auto_link.go b/cmd/workflow/deploy/auto_link.go index 2ee140bf..7e393dc3 100644 --- a/cmd/workflow/deploy/auto_link.go +++ b/cmd/workflow/deploy/auto_link.go @@ -25,7 +25,7 @@ const ( func (h *handler) ensureOwnerLinkedOrFail(onChain *settings.OnChainRegistry) error { ownerAddr := common.HexToAddress(h.inputs.WorkflowOwner) - linked, err := h.wrc.IsOwnerLinked(ownerAddr) + linked, err := h.wrc.IsOwnerLinked(h.execCtx, ownerAddr) if err != nil { return fmt.Errorf("failed to check owner link status: %w", err) } @@ -66,7 +66,7 @@ func (h *handler) ensureOwnerLinkedOrFail(onChain *settings.OnChainRegistry) err func (h *handler) autoLinkMSIGAndExit(onChain *settings.OnChainRegistry) (halt bool, err error) { ownerAddr := common.HexToAddress(h.inputs.WorkflowOwner) - linked, err := h.wrc.IsOwnerLinked(ownerAddr) + linked, err := h.wrc.IsOwnerLinked(h.execCtx, ownerAddr) if err != nil { return false, fmt.Errorf("failed to check owner link status: %w", err) } @@ -107,7 +107,7 @@ func (h *handler) tryAutoLink(onChain *settings.OnChainRegistry) error { EnvironmentSet: h.environmentSet, } - return linkkey.Exec(rtx, linkkey.Inputs{ + return linkkey.Exec(h.execCtx, rtx, linkkey.Inputs{ WorkflowOwner: h.inputs.WorkflowOwner, WorkflowRegistryContractAddress: onChain.Address(), WorkflowOwnerLabel: h.inputs.OwnerLabel, diff --git a/cmd/workflow/deploy/deploy_test.go b/cmd/workflow/deploy/deploy_test.go index 72632ce6..aa0a7907 100644 --- a/cmd/workflow/deploy/deploy_test.go +++ b/cmd/workflow/deploy/deploy_test.go @@ -805,7 +805,7 @@ type fakeUserDonLimitClient struct { workflowsByOwnerName []workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView } -func (f fakeUserDonLimitClient) CheckUserDonLimit(owner common.Address, donFamily string, pending uint32) error { +func (f fakeUserDonLimitClient) CheckUserDonLimit(_ context.Context, owner common.Address, donFamily string, pending uint32) error { var currentActive uint32 for _, workflow := range f.workflowsByOwner { if workflow.Owner == owner && workflow.Status == workflowStatusActive && workflow.DonFamily == donFamily { @@ -819,7 +819,7 @@ func (f fakeUserDonLimitClient) CheckUserDonLimit(owner common.Address, donFamil return nil } -func (f fakeUserDonLimitClient) GetWorkflowListByOwnerAndName(common.Address, string, *big.Int, *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { +func (f fakeUserDonLimitClient) GetWorkflowListByOwnerAndName(_ context.Context, _ common.Address, _ string, _, _ *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) { return f.workflowsByOwnerName, nil } @@ -879,7 +879,7 @@ func TestCheckUserDonLimitBeforeDeploy(t *testing.T) { } nameLookup := fakeUserDonLimitClient{} - err := checkUserDonLimitBeforeDeploy(client, nameLookup, owner, donFamily, workflowName, true, nil) + err := checkUserDonLimitBeforeDeploy(context.Background(), client, nameLookup, owner, donFamily, workflowName, true, nil) require.Error(t, err) assert.Contains(t, err.Error(), "workflow limit reached") }) @@ -898,7 +898,7 @@ func TestCheckUserDonLimitBeforeDeploy(t *testing.T) { }, } - err := checkUserDonLimitBeforeDeploy(client, nameLookup, owner, donFamily, workflowName, false, nil) + err := checkUserDonLimitBeforeDeploy(context.Background(), client, nameLookup, owner, donFamily, workflowName, false, nil) require.NoError(t, err) }) @@ -912,7 +912,7 @@ func TestCheckUserDonLimitBeforeDeploy(t *testing.T) { nameLookup := fakeUserDonLimitClient{} existingStatus := uint8(0) - err := checkUserDonLimitBeforeDeploy(client, nameLookup, owner, donFamily, workflowName, true, &existingStatus) + err := checkUserDonLimitBeforeDeploy(context.Background(), client, nameLookup, owner, donFamily, workflowName, true, &existingStatus) require.NoError(t, err) }) } diff --git a/cmd/workflow/deploy/limits.go b/cmd/workflow/deploy/limits.go index 4a93f003..a58561ad 100644 --- a/cmd/workflow/deploy/limits.go +++ b/cmd/workflow/deploy/limits.go @@ -1,6 +1,7 @@ package deploy import ( + "context" "fmt" "math/big" @@ -16,14 +17,15 @@ const ( ) type workflowNameLookupClient interface { - GetWorkflowListByOwnerAndName(owner common.Address, workflowName string, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) + GetWorkflowListByOwnerAndName(ctx context.Context, owner common.Address, workflowName string, start, limit *big.Int) ([]workflow_registry_v2_wrapper.WorkflowRegistryWorkflowMetadataView, error) } type userDonLimitChecker interface { - CheckUserDonLimit(owner common.Address, donFamily string, pending uint32) error + CheckUserDonLimit(ctx context.Context, owner common.Address, donFamily string, pending uint32) error } func checkUserDonLimitBeforeDeploy( + ctx context.Context, limitChecker userDonLimitChecker, nameLookup workflowNameLookupClient, owner common.Address, @@ -38,7 +40,7 @@ func checkUserDonLimitBeforeDeploy( pending := uint32(1) if !keepAlive { - activeSameName, err := countActiveWorkflowsByOwnerNameAndDON(nameLookup, owner, workflowName, donFamily) + activeSameName, err := countActiveWorkflowsByOwnerNameAndDON(ctx, nameLookup, owner, workflowName, donFamily) if err != nil { return fmt.Errorf("failed to check active workflows for %s on DON %s: %w", workflowName, donFamily, err) } @@ -53,10 +55,11 @@ func checkUserDonLimitBeforeDeploy( return nil } - return limitChecker.CheckUserDonLimit(owner, donFamily, pending) + return limitChecker.CheckUserDonLimit(ctx, owner, donFamily, pending) } func countActiveWorkflowsByOwnerNameAndDON( + ctx context.Context, wrc workflowNameLookupClient, owner common.Address, workflowName string, @@ -67,7 +70,7 @@ func countActiveWorkflowsByOwnerNameAndDON( limit := big.NewInt(workflowListPageSize) for { - list, err := wrc.GetWorkflowListByOwnerAndName(owner, workflowName, start, limit) + list, err := wrc.GetWorkflowListByOwnerAndName(ctx, owner, workflowName, start, limit) if err != nil { return 0, err } diff --git a/cmd/workflow/deploy/register.go b/cmd/workflow/deploy/register.go index 6c47e237..29c6ac67 100644 --- a/cmd/workflow/deploy/register.go +++ b/cmd/workflow/deploy/register.go @@ -57,7 +57,7 @@ func (h *handler) handleUpsert(params client.RegisterWorkflowV2Parameters, onCha workflowName := h.inputs.WorkflowName workflowTag := h.inputs.WorkflowTag h.log.Debug().Interface("Workflow parameters", params).Msg("Registering workflow...") - txOut, err := h.wrc.UpsertWorkflow(params) + txOut, err := h.wrc.UpsertWorkflow(h.execCtx, params) if err != nil { return fmt.Errorf("failed to register workflow: %w", err) } diff --git a/cmd/workflow/deploy/register_test.go b/cmd/workflow/deploy/register_test.go index da3b0241..b039aaf5 100644 --- a/cmd/workflow/deploy/register_test.go +++ b/cmd/workflow/deploy/register_test.go @@ -1,6 +1,7 @@ package deploy import ( + "context" "path/filepath" "testing" @@ -47,7 +48,7 @@ func TestWorkflowUpsert(t *testing.T) { ctx, buf := simulatedEnvironment.NewRuntimeContextWithBufferedOutput() handler := newHandler(ctx, buf) - wrc, err := handler.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := handler.clientFactory.NewWorkflowRegistryV2Client(context.Background()) require.NoError(t, err) handler.wrc = wrc @@ -62,6 +63,7 @@ func TestWorkflowUpsert(t *testing.T) { } handler.workflowArtifact = &wfArt + handler.execCtx = context.Background() onChain, err := settings.AsOnChain(ctx.ResolvedRegistry, "test") require.NoError(t, err) diff --git a/cmd/workflow/deploy/registry_deploy_strategy_onchain.go b/cmd/workflow/deploy/registry_deploy_strategy_onchain.go index 0d1943cd..032de838 100644 --- a/cmd/workflow/deploy/registry_deploy_strategy_onchain.go +++ b/cmd/workflow/deploy/registry_deploy_strategy_onchain.go @@ -33,7 +33,7 @@ func newOnchainRegistryDeployStrategy(h *handler) (*onchainRegistryDeployStrateg a.wg.Add(1) go func() { defer a.wg.Done() - wrc, err := h.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.clientFactory.NewWorkflowRegistryV2Client(h.execCtx) if err != nil { a.initErr = fmt.Errorf("failed to create workflow registry client: %w", err) return @@ -72,7 +72,7 @@ func (a *onchainRegistryDeployStrategy) RunPreDeployChecks() error { } func (a *onchainRegistryDeployStrategy) CheckWorkflowExists(workflowOwner, workflowName, workflowTag, workflowID string) (bool, *uint8, error) { - workflow, err := a.wrc.GetWorkflow(common.HexToAddress(workflowOwner), workflowName, workflowTag) + workflow, err := a.wrc.GetWorkflow(a.h.execCtx, common.HexToAddress(workflowOwner), workflowName, workflowTag) if err != nil { return false, nil, err } @@ -92,6 +92,7 @@ func (a *onchainRegistryDeployStrategy) Upsert() error { h := a.h if err := checkUserDonLimitBeforeDeploy( + h.execCtx, a.wrc, a.wrc, common.HexToAddress(h.inputs.WorkflowOwner), diff --git a/cmd/workflow/pause/registry_pause_strategy_onchain.go b/cmd/workflow/pause/registry_pause_strategy_onchain.go index 1003b739..9e403dd8 100644 --- a/cmd/workflow/pause/registry_pause_strategy_onchain.go +++ b/cmd/workflow/pause/registry_pause_strategy_onchain.go @@ -34,7 +34,7 @@ func newOnchainRegistryPauseStrategy(h *handler) (*onchainRegistryPauseStrategy, a.wg.Add(1) go func() { defer a.wg.Done() - wrc, err := h.clientFactory.NewWorkflowRegistryV2Client() + wrc, err := h.clientFactory.NewWorkflowRegistryV2Client(h.execCtx) if err != nil { a.initErr = fmt.Errorf("failed to create workflow registry client: %w", err) return @@ -57,7 +57,7 @@ func (a *onchainRegistryPauseStrategy) Pause() error { ui.Dim(fmt.Sprintf("Fetching workflows to pause... Name=%s, Owner=%s", workflowName, workflowOwner.Hex())) - workflows, err := workflowcommon.FetchAllWorkflowsByOwnerAndName(a.wrc, workflowOwner, workflowName) + workflows, err := workflowcommon.FetchAllWorkflowsByOwnerAndName(h.execCtx, a.wrc, workflowOwner, workflowName) if err != nil { return fmt.Errorf("failed to list workflows: %w", err) } @@ -82,7 +82,7 @@ func (a *onchainRegistryPauseStrategy) Pause() error { ui.Dim(fmt.Sprintf("Processing batch pause... count=%d", len(activeWorkflowIDs))) - txOut, err := a.wrc.BatchPauseWorkflows(activeWorkflowIDs) + txOut, err := a.wrc.BatchPauseWorkflows(h.execCtx, activeWorkflowIDs) if err != nil { return fmt.Errorf("failed to batch pause workflows: %w", err) } diff --git a/internal/testutil/chainsim/simulated_client_factory.go b/internal/testutil/chainsim/simulated_client_factory.go index 9dc8a7b5..6ce1fba2 100644 --- a/internal/testutil/chainsim/simulated_client_factory.go +++ b/internal/testutil/chainsim/simulated_client_factory.go @@ -1,6 +1,8 @@ package chainsim import ( + "context" + "github.com/rs/zerolog" "github.com/smartcontractkit/chainlink-testing-framework/seth" @@ -22,7 +24,7 @@ func NewSimulatedClientFactory(logger *zerolog.Logger, ethClient *seth.Client, s } } -func (f *testFactoryImpl) NewWorkflowRegistryV2Client() (*client.WorkflowRegistryV2Client, error) { +func (f *testFactoryImpl) NewWorkflowRegistryV2Client(ctx context.Context) (*client.WorkflowRegistryV2Client, error) { txcConfig := client.TxClientConfig{ TxType: client.Regular, LedgerConfig: &client.LedgerConfig{LedgerEnabled: false}, diff --git a/internal/testutil/chainsim/simulated_workflow_registry_contract.go b/internal/testutil/chainsim/simulated_workflow_registry_contract.go index 9ccc7cc4..7c68622c 100644 --- a/internal/testutil/chainsim/simulated_workflow_registry_contract.go +++ b/internal/testutil/chainsim/simulated_workflow_registry_contract.go @@ -1,6 +1,7 @@ package chainsim import ( + "context" "crypto/sha256" "encoding/hex" "fmt" @@ -36,11 +37,11 @@ func DeployWorkflowRegistry(t *testing.T, ethClient *seth.Client, chain *Simulat } workflowRegistryClient := client.NewWorkflowRegistryV2Client(logger, ethClient, deployedContract.Address.Hex(), txcConfig) - err = workflowRegistryClient.UpdateAllowedSigners([]common.Address{common.HexToAddress(TestAddress)}, true) + err = workflowRegistryClient.UpdateAllowedSigners(context.Background(), []common.Address{common.HexToAddress(TestAddress)}, true) chain.Backend.Commit() require.NoError(t, err, "Failed to update authorized addresses") - err = workflowRegistryClient.SetDonLimit("zone-a", 1000, 100) + err = workflowRegistryClient.SetDonLimit(context.Background(), "zone-a", 1000, 100) chain.Backend.Commit() require.NoError(t, err, "Failed to update allowed DONs") @@ -63,7 +64,7 @@ func linkOwner(wrc *client.WorkflowRegistryV2Client) error { const LinkRequestType uint8 = 0 - version, err := wrc.TypeAndVersion() + version, err := wrc.TypeAndVersion(context.Background()) if err != nil { return err } @@ -113,7 +114,7 @@ func linkOwner(wrc *client.WorkflowRegistryV2Client) error { //t.Logf("v: %d, r: %s, s: %s", v, r.Text(16), s.Text(16)) - _, err = wrc.LinkOwner(validityTimestamp, common.HexToHash(ownershipProof), signature) + _, err = wrc.LinkOwner(context.Background(), validityTimestamp, common.HexToHash(ownershipProof), signature) if err != nil { return err } diff --git a/internal/testutil/workflow/test_workflow.go b/internal/testutil/workflow/test_workflow.go index 5c43c1cd..7451fd06 100644 --- a/internal/testutil/workflow/test_workflow.go +++ b/internal/testutil/workflow/test_workflow.go @@ -1,6 +1,7 @@ package workflowtest import ( + "context" "testing" "github.com/ethereum/go-ethereum/common" @@ -26,6 +27,6 @@ func RegisterWorkflow(t *testing.T, wrc *client.WorkflowRegistryV2Client, workfl DonFamily: "1", } - _, err = wrc.UpsertWorkflow(params) + _, err = wrc.UpsertWorkflow(context.Background(), params) require.NoError(t, err, "Failed to register workflow") }