feat: wallet private key export API with password verification
All checks were successful
Server CI/CD / lint-and-build (push) Successful in 39s
Server CI/CD / deploy (push) Successful in 52s

This commit is contained in:
2026-03-23 10:52:27 +09:00
parent 10a3f0156b
commit 0cd0d2a402
5 changed files with 75 additions and 8 deletions

View File

@@ -21,14 +21,15 @@ import (
)
type Service struct {
repo *Repository
client *Client
chainID string
operatorWallet *wallet.Wallet
encKeyBytes []byte // 32-byte AES-256 key
userResolver func(username string) (uint, error)
operatorMu sync.Mutex // serialises operator-nonce transactions
userMu sync.Map // per-user mutex (keyed by userID uint)
repo *Repository
client *Client
chainID string
operatorWallet *wallet.Wallet
encKeyBytes []byte // 32-byte AES-256 key
userResolver func(username string) (uint, error)
passwordVerifier func(userID uint, password string) error
operatorMu sync.Mutex // serialises operator-nonce transactions
userMu sync.Map // per-user mutex (keyed by userID uint)
}
// SetUserResolver sets the callback that resolves username → userID.
@@ -36,6 +37,24 @@ func (s *Service) SetUserResolver(fn func(username string) (uint, error)) {
s.userResolver = fn
}
func (s *Service) SetPasswordVerifier(fn func(userID uint, password string) error) {
s.passwordVerifier = fn
}
func (s *Service) ExportPrivKey(userID uint, password string) (string, error) {
if s.passwordVerifier == nil {
return "", fmt.Errorf("password verifier not configured")
}
if err := s.passwordVerifier(userID, password); err != nil {
return "", err
}
w, _, err := s.loadUserWallet(userID)
if err != nil {
return "", err
}
return w.PrivKey().Hex(), nil
}
// resolveUsername converts a username to the user's on-chain pubKeyHex.
// If the user exists but has no wallet (e.g. legacy user or failed creation),
// a wallet is auto-created on the fly.