UNPKG

@ledgerhq/hw-app-btc

Version:
92 lines 4.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.arePathsEqual = arePathsEqual; exports.validateAccountPathConsistency = validateAccountPathConsistency; exports.validateScriptTypeConsistency = validateScriptTypeConsistency; exports.resolveAccountPathFromOptions = resolveAccountPathFromOptions; exports.determineInputScriptType = determineInputScriptType; exports.analyzeInput = analyzeInput; exports.analyzeAllInputs = analyzeAllInputs; const psbtv2_1 = require("@ledgerhq/psbtv2"); const bip32_1 = require("../bip32"); const derivationAccessors_1 = require("./derivationAccessors"); function arePathsEqual(path1, path2) { if (path1.length !== path2.length) return false; return path1.every((elem, idx) => elem === path2[idx]); } function validateAccountPathConsistency(accountPath, newAccountPath, inputIndex) { if (accountPath.length > 0 && !arePathsEqual(accountPath, newAccountPath)) { throw new Error(`Mixed accounts detected in PSBT. Input ${inputIndex} uses account path ` + `${(0, bip32_1.pathArrayToString)(newAccountPath)} but expected ` + `${(0, bip32_1.pathArrayToString)(accountPath)}. All internal inputs must belong to the same account.`); } } function validateScriptTypeConsistency(detectedScriptType, newScriptType, inputIndex) { if (detectedScriptType && newScriptType && detectedScriptType !== newScriptType) { throw new Error(`Mixed input types detected in PSBT. Input ${inputIndex} uses ${newScriptType} ` + `but expected ${detectedScriptType}. All internal inputs must use the same script type.`); } } function resolveAccountPathFromOptions(accountPathOption) { if (!accountPathOption) { throw new Error("No internal inputs found in PSBT (no BIP32 derivation matching device fingerprint) " + "and no account path provided in options. Please provide accountPath in options " + "(e.g., \"m/84'/0'/0'\" for native segwit)"); } return (0, bip32_1.pathStringToArray)(accountPathOption); } /** * Determines the script type for a single input from witness UTXO or redeem script. */ function determineInputScriptType(psbt, inputIndex) { const witnessUtxo = psbt.getInputWitnessUtxo(inputIndex); if (witnessUtxo) { return (0, psbtv2_1.detectScriptType)(witnessUtxo.scriptPubKey); } const redeemScript = psbt.getInputRedeemScript(inputIndex); if (redeemScript) { return "p2sh-p2wpkh"; } return undefined; } /** * Analyzes a single input to determine if it belongs to the connected signer and extracts account path and script type. */ function analyzeInput(psbt, inputIndex, masterFp) { const derivationResult = (0, derivationAccessors_1.checkBip32Derivation)(psbt, inputIndex, masterFp); const scriptType = determineInputScriptType(psbt, inputIndex); return { belongsToSigner: derivationResult.belongsToSigner, accountPath: derivationResult.accountPath, scriptType, }; } /** * Analyzes all inputs and returns resolved account path, detected script type, and internal input indices. */ function analyzeAllInputs(psbt, inputCount, masterFp, accountPathOption) { const internalInputIndices = []; let accountPath = []; let detectedScriptType; for (let i = 0; i < inputCount; i++) { const inputInfo = analyzeInput(psbt, i, masterFp); if (!inputInfo.belongsToSigner) { continue; } internalInputIndices.push(i); validateAccountPathConsistency(accountPath, inputInfo.accountPath, i); if (accountPath.length === 0) { accountPath = inputInfo.accountPath; } validateScriptTypeConsistency(detectedScriptType, inputInfo.scriptType, i); if (!detectedScriptType) { detectedScriptType = inputInfo.scriptType; } } if (internalInputIndices.length === 0) { accountPath = resolveAccountPathFromOptions(accountPathOption); } return { accountPath, detectedScriptType, internalInputIndices }; } //# sourceMappingURL=inputAnalysis.js.map