Skip to main content

Generate the unsigned data

Upon successfully establishing a connection between the software wallet and Keystone, the subsequent action involves generating the unsigned transaction data. This data must then be encoded into a QR code, which serves as a secure intermediary for transmitting the transaction details or signing messages.

Let's use an ETH transaction as a example, The following code utilizes the @ethereumjs/tx library to generate an unsigned transaction. This unsigned transaction's hexadecimal data can subsequently be encoded into the ethSignRequest. The KeystoneSDK facilitates the encoding of this complete data set. Furthermore, the AnimatedQRCode React Component can be employed to visually represent this encoded data as a QR Code, thereby enabling efficient and secure data sharing.

import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx';
import { Hardfork, Chain, Common } from '@ethereumjs/common';
import KeystoneSDK, {KeystoneEthereumSDK} from "@keystonehq/keystone-sdk";
import {AnimatedQRCode} from "@keystonehq/animated-qr";

// Initialize a Common instance specifying the Ethereum mainnet and the London hardfork.
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London });

// Define the transaction parameters for an EIP-1559 transaction.
const txParams = {
to: "0x31bA53Ca350975007B27CF43AcB4D9Bc3db2641c", // Recipient address
gasLimit: 35552, // Gas limit for the transaction
maxPriorityFeePerGas: 75853, // Max priority fee per gas
maxFeePerGas: 121212, // Max fee per gas
data: "0x", // Data sent with the transaction
nonce: 1, // Nonce for the transaction
value: 1200000000000000000n, // Transaction value in wei (1.2 ETH)
};

// Create an EIP-1559 transaction object from the transaction parameters.
const eip1559Tx = FeeMarketEIP1559Transaction.fromTxData(txParams, { common });

// Generate the unsigned message from the transaction object.
const unsignedMessage = Buffer.from(eip1559Tx.getMessageToSign(false)).toString("hex");

// Define the Ethereum signing request parameters.
const ethSignRequest = {
requestId: uuid.v4(), // Unique request ID
signData: unsignedMessage, // Unsigned message data
dataType: KeystoneEthereumSDK.DataType.typedTransaction, // Data type indicating a typed transaction
path: "m/44'/60'/0'/0/0", // BIP44 path for the transaction
xfp: "F23F9FD2", // Master fingerprint
chainId: 1, // Ethereum mainnet chain ID
origin: "MetaMask" // Origin of the sign request
}

// React component to generate and display an animated QR code for the Ethereum signing request.
const Ethereum = () => {
const keystoneSDK = new KeystoneSDK();

// Generate the sign request using the Keystone SDK.
const ur = keystoneSDK.eth.generateSignRequest(ethSignRequest);

// Return an AnimatedQRCode component displaying the generated sign request.
return <AnimatedQRCode type={ur.type} cbor={ur.cbor.toString("hex")} />
}

When dealing with large volumes of unsigned data, a single QR Code image may not be sufficient to encapsulate the entire dataset. To address this limitation, an animated QR Code can be employed.