package vault import ( "context" "math/big" "strings" "github.com/ethereum/go-ethereum/core/types" "github.com/tech/sendico/pkg/vault/managedkey" "go.uber.org/zap" "github.com/tech/sendico/gateway/chain/internal/keymanager" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/mlogger" pmodel "github.com/tech/sendico/pkg/model" ) // Config describes how to connect to Vault for managed wallet keys. type Config = managedkey.Config // Manager implements the keymanager.Manager contract backed by HashiCorp Vault. type Manager struct { logger mlogger.Logger keys managedkey.Service } // New constructs a Vault-backed key manager. func New(logger mlogger.Logger, cfg Config) (*Manager, error) { if logger == nil { return nil, merrors.InvalidArgument("vault key manager: logger is required") } keys, err := managedkey.New(managedkey.Options{ Logger: logger, Config: managedkey.Config(cfg), Component: "vault key manager", DefaultKeyPrefix: "gateway/chain/wallets", }) if err != nil { logger.Error("Failed to initialise vault key manager", zap.Error(err)) return nil, err } return &Manager{ logger: logger.Named("vault"), keys: keys, }, nil } // CreateManagedWalletKey creates a new managed wallet key and stores it in Vault. func (m *Manager) CreateManagedWalletKey(ctx context.Context, walletRef string, network pmodel.ChainNetwork) (*keymanager.ManagedWalletKey, error) { if network == pmodel.ChainNetworkUnspecified { m.logger.Warn("Network missing for managed key creation", zap.String("wallet_ref", walletRef)) return nil, merrors.InvalidArgument("vault key manager: network is required") } networkValue := strings.TrimSpace(string(network)) if networkValue == "" { m.logger.Warn("Network missing for managed key creation", zap.String("wallet_ref", walletRef)) return nil, merrors.InvalidArgument("vault key manager: network is required") } created, err := m.keys.CreateManagedWalletKey(ctx, walletRef, networkValue) if err != nil { m.logger.Warn("Failed to create managed wallet key", zap.String("wallet_ref", walletRef), zap.String("network", networkValue), zap.Error(err)) return nil, err } return &keymanager.ManagedWalletKey{ KeyID: created.KeyID, Address: created.Address, PublicKey: created.PublicKey, }, nil } // SignTransaction loads the key material from Vault and signs the transaction. func (m *Manager) SignTransaction(ctx context.Context, keyID string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { signed, err := m.keys.SignEVMTransaction(ctx, keyID, tx, chainID) if err != nil { m.logger.Warn("Failed to sign transaction", zap.String("key_id", keyID), zap.Error(err)) return nil, err } return signed, nil } var _ keymanager.Manager = (*Manager)(nil)