Сообщение об ошибке
invalid signature length
Также выводится как
- Error: invalid signature length
viem (TypeScript) — recoverMessageAddress / recoverAddress / recoverTypedDataAddress / recoverPublicKey
Что это означает
Функции восстановления в viem принимают подпись в hex или в байтах длиной ровно 65 байт (r‖s‖v) и при любой другой длине останавливаются с этим простым `Error` — в том числе для 64-байтной компактной формы EIP-2098, которую viem поддерживает только через явные вспомогательные функции преобразования. Ничего не восстановлено: подпись в другом формате, или это вообще не подпись EOA.
Почему это происходит
64-байтная компактная подпись (EIP-2098)
частоНекоторые кошельки, ретрансляторы (relayers) и контракты хранят подписи в компактной форме (yParity упакован в s). ethers принимает её напрямую, а функции `recover*` в viem — нет.
Подпись смарт-аккаунта
частоПодписи ERC-1271 и ERC-6492 от Safe, Coinbase Smart Wallet и других смарт-аккаунтов длиннее 65 байт, и восстановить по ним адрес нельзя; их необходимо проверять через контракт аккаунта.
Base64 или двойное hex-кодирование
иногдаПодпись, переданная в base64, или hex-строка, повторно закодированная в hex, после чтения в viem имеет неверную длину.
Как исправить
- 1.
Преобразуйте компактные подписи перед восстановлением
`parseCompactSignature` вместе с `compactSignatureToSignature` превращают 64-байтную форму в 65-байтную.
ts import { compactSignatureToSignature, parseCompactSignature, recoverMessageAddress, serializeSignature, size } from "viem"; const sig = size(signature) === 64 ? serializeSignature(compactSignatureToSignature(parseCompactSignature(signature))) : signature; const signer = await recoverMessageAddress({ message, signature: sig }); - 2.
Используйте publicClient.verifyMessage для любых кошельков
Публичный клиент проверяет подписи EOA локально, а подписи смарт-аккаунтов — через ERC-1271/ERC-6492, поэтому один и тот же код работает с кошельками любого типа.
ts import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; // Handles EOAs, ERC-1271 smart accounts and ERC-6492 (undeployed) accounts. const client = createPublicClient({ chain: mainnet, transport: http(process.env.RPC_URL) }); const valid = await client.verifyMessage({ address, message, signature });