BTC PSBT
PSBT data handling for offline signing with animated UR codes.
Type Map
- Request/response UR type:
crypto-psbt - See also: Basic API (UR primitives and structures)
Steps
- Build an unsigned PSBT with your wallet backend
- Encode PSBT → UR (
crypto-psbt) and display as animated QR - Device scans → returns signed PSBT as
crypto-psbt - Finalize and broadcast
Tip: Keep PSBT size within practical QR limits; split across frames as needed.
Samples
Encode unsigned PSBT → animated QR
import { CryptoPSBT } from "@keystonehq/bc-ur-registry-btc";
import { airGapUrUtils } from "@keystonehq/keystone-sdk";
const psbtBytes = Buffer.from(unsignedPsbtBase64, "base64");
const req = CryptoPSBT.fromPSBT(psbtBytes); // 也可以写成 new CryptoPSBT(psbtBytes)
const ur = req.toUR();
const frames = airGapUrUtils.urToQrcode(ur); // Render the frames in your UI
Decode animated QR → signed PSBT
import { URDecoder } from "@ngraveio/bc-ur";
import { CryptoPSBT } from "@keystonehq/bc-ur-registry-btc";
const dec = new URDecoder();
// For each frame string scanned by the camera:
// hand frameString to dec.receivePart for each frame
if (dec.isComplete()) {
const ur = dec.resultUR(); // the UR type should resolve to 'crypto-psbt'
const psbt = CryptoPSBT.fromCBOR(ur.cbor);
const signedPsbt = psbt.getPSBT(); // PSBT buffer after full or partial signing
// Finalize and broadcast it through your backend
}