Skip to Content
On this page

ETHSignature

ETHSignature decodes an Ethereum signature returned by the device. The class name uses uppercase ETH.

Its constructor accepts signature: Buffer, an optional requestId: Buffer, and an optional origin: string.

Decode the response

Create a new decoder for each scanning session. Call onSignatureFrame for every camera frame. Keep expectedRequestId from the original request; do not accept a signature from another request.

import { URDecoder } from '@ngraveio/bc-ur'; import { ETHSignature } from '@keystonehq/bc-ur-registry-eth'; const decoder = new URDecoder(); function onSignatureFrame(frame: string, expectedRequestId: string) { decoder.receivePart(frame); if (decoder.isError()) { throw new Error('Could not decode the signature QR code'); } if (!decoder.isSuccess()) return; const ur = decoder.resultUR(); if (ur.type !== 'eth-signature') { throw new Error('Expected an eth-signature response'); } const result = ETHSignature.fromCBOR(ur.cbor); const expectedId = Buffer.from(expectedRequestId.replace(/-/g, ''), 'hex'); const receivedId = result.getRequestId(); if (!receivedId || !receivedId.equals(expectedId)) { throw new Error('Signature request ID does not match'); } const signature = result.getSignature(); if (signature.length !== 65) { throw new Error('Expected a 65-byte Ethereum signature'); } return { r: signature.subarray(0, 32), s: signature.subarray(32, 64), v: signature[64], }; }

Use your Ethereum library to interpret v for the original transaction type and chain, recover the signer, and assemble the signed transaction. Reuse the exact unsigned transaction that was sent to the device. Do not attach this signature to a newly constructed or modified transaction.

Last updated on