Files
FrenoCorp/node_modules/viem/utils/signature/recoverPublicKey.ts
Michael Freno 7c684a42cc FRE-600: Fix code review blockers
- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-25 00:08:01 -04:00

65 lines
2.0 KiB
TypeScript

import type { ErrorType } from '../../errors/utils.js'
import type { ByteArray, Hex, Signature } from '../../types/misc.js'
import { type IsHexErrorType, isHex } from '../data/isHex.js'
import { size } from '../data/size.js'
import {
type HexToNumberErrorType,
hexToBigInt,
hexToNumber,
} from '../encoding/fromHex.js'
import { toHex } from '../encoding/toHex.js'
export type RecoverPublicKeyParameters = {
hash: Hex | ByteArray
signature: Hex | ByteArray | Signature
}
export type RecoverPublicKeyReturnType = Hex
export type RecoverPublicKeyErrorType =
| HexToNumberErrorType
| IsHexErrorType
| ErrorType
export async function recoverPublicKey({
hash,
signature,
}: RecoverPublicKeyParameters): Promise<RecoverPublicKeyReturnType> {
const hashHex = isHex(hash) ? hash : toHex(hash)
const { secp256k1 } = await import('@noble/curves/secp256k1')
const signature_ = (() => {
// typeof signature: `Signature`
if (typeof signature === 'object' && 'r' in signature && 's' in signature) {
const { r, s, v, yParity } = signature
const yParityOrV = Number(yParity ?? v)!
const recoveryBit = toRecoveryBit(yParityOrV)
return new secp256k1.Signature(
hexToBigInt(r),
hexToBigInt(s),
).addRecoveryBit(recoveryBit)
}
// typeof signature: `Hex | ByteArray`
const signatureHex = isHex(signature) ? signature : toHex(signature)
if (size(signatureHex) !== 65) throw new Error('invalid signature length')
const yParityOrV = hexToNumber(`0x${signatureHex.slice(130)}`)
const recoveryBit = toRecoveryBit(yParityOrV)
return secp256k1.Signature.fromCompact(
signatureHex.substring(2, 130),
).addRecoveryBit(recoveryBit)
})()
const publicKey = signature_
.recoverPublicKey(hashHex.substring(2))
.toHex(false)
return `0x${publicKey}`
}
function toRecoveryBit(yParityOrV: number) {
if (yParityOrV === 0 || yParityOrV === 1) return yParityOrV
if (yParityOrV === 27) return 0
if (yParityOrV === 28) return 1
throw new Error('Invalid yParityOrV value')
}