From b868bd91dc411b3d5cfb4a004a505094c4a2ec20 Mon Sep 17 00:00:00 2001 From: ByteZhang Date: Wed, 15 Apr 2026 11:56:36 +0800 Subject: [PATCH] feat: add tx body parser helpers + bump to 1.1.11 Expose three CardanoWasm-backed helpers on onekeyUtils: - parseRawTxInputs: returns the full ordered input set ({prev_hash, prev_index}[]) from a rawTxHex - parseRawTxBodyStakeInfo: returns hasCertificates / hasWithdrawals / requiredSignerHashes for stake-witness-necessity decisions - extractStakeKeyHashFromBaseAddress: returns the hex stake key hash for key-credential base addresses, null otherwise Used by app-monorepo's KeyringHardware on the Cardano dApp signOnly path to (a) rebuild the full firmware-side inputs set including external contract UTXOs, and (b) drop the unneeded stake vkey witness on script-authorized DeFi mints (Minswap LP etc.) so the broadcast body fits the dApp's fee budget. Helpers were previously duplicated in app-monorepo; centralizing them here so all hosts share one implementation. --- package.json | 2 +- src/utils/onekey/index.ts | 8 ++++ src/utils/onekey/parseRawTx.ts | 79 ++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/utils/onekey/parseRawTx.ts diff --git a/package.json b/package.json index 3508282..371cc8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onekeyfe/cardano-coin-selection-asmjs", - "version": "1.1.10", + "version": "1.1.11", "description": "", "keywords": [ "coin selection" diff --git a/src/utils/onekey/index.ts b/src/utils/onekey/index.ts index 48a852e..f9297ef 100644 --- a/src/utils/onekey/index.ts +++ b/src/utils/onekey/index.ts @@ -3,6 +3,11 @@ import { signTransaction, signTx } from './signTx'; import { dAppUtils } from './dapp'; import { txToOneKey } from './txToOneKey'; import { hasSetTagWithBody } from './hasSetTag'; +import { + parseRawTxInputs, + parseRawTxBodyStakeInfo, + extractStakeKeyHashFromBaseAddress, +} from './parseRawTx'; const onekeyUtils = { composeTxPlan, @@ -10,6 +15,9 @@ const onekeyUtils = { signTx, txToOneKey, hasSetTagWithBody, + parseRawTxInputs, + parseRawTxBodyStakeInfo, + extractStakeKeyHashFromBaseAddress, }; export { onekeyUtils, dAppUtils }; diff --git a/src/utils/onekey/parseRawTx.ts b/src/utils/onekey/parseRawTx.ts new file mode 100644 index 0000000..ecd2dc4 --- /dev/null +++ b/src/utils/onekey/parseRawTx.ts @@ -0,0 +1,79 @@ +import * as CardanoWasm from '@emurgo/cardano-serialization-lib-asmjs'; + +export type IParsedRawTxInput = { + prev_hash: string; + prev_index: number; +}; + +export type IParsedRawTxBodyStakeInfo = { + hasCertificates: boolean; + hasWithdrawals: boolean; + requiredSignerHashes: string[]; +}; + +export const parseRawTxInputs = ( + rawTxHex: string, +): Promise => { + const tx = CardanoWasm.Transaction.from_hex(rawTxHex); + const inputs = tx.body().inputs(); + const out: IParsedRawTxInput[] = []; + for (let i = 0; i < inputs.len(); i += 1) { + const input = inputs.get(i); + out.push({ + prev_hash: input.transaction_id().to_hex(), + prev_index: input.index(), + }); + } + return Promise.resolve(out); +}; + +export const parseRawTxBodyStakeInfo = ( + rawTxHex: string, +): Promise => { + const tx = CardanoWasm.Transaction.from_hex(rawTxHex); + const body = tx.body(); + + const certs = body.certs(); + const hasCertificates = !!certs && certs.len() > 0; + + const withdrawals = body.withdrawals(); + const hasWithdrawals = !!withdrawals && withdrawals.keys().len() > 0; + + const requiredSigners = body.required_signers(); + const requiredSignerHashes: string[] = []; + if (requiredSigners) { + for (let i = 0; i < requiredSigners.len(); i += 1) { + requiredSignerHashes.push(requiredSigners.get(i).to_hex()); + } + } + + return Promise.resolve({ + hasCertificates, + hasWithdrawals, + requiredSignerHashes, + }); +}; + +// Returns the hex stake key hash for key-credential base addresses (types 0 +// and 1 in Cardano address layout); returns null for script-credential stakes +// or non-base addresses. Caller should treat null as "cannot safely filter +// stake witness". +export const extractStakeKeyHashFromBaseAddress = ( + addr: string, +): Promise => { + try { + const address = CardanoWasm.Address.from_bech32(addr); + const baseAddress = CardanoWasm.BaseAddress.from_address(address); + if (!baseAddress) return Promise.resolve(null); + const stakeCred = baseAddress.stake_cred(); + if (stakeCred.kind() !== CardanoWasm.CredKind.Key) { + return Promise.resolve(null); + } + // spell-checker:disable-next-line + const stakeKey = stakeCred.to_keyhash(); + if (!stakeKey) return Promise.resolve(null); + return Promise.resolve(stakeKey.to_hex()); + } catch { + return Promise.resolve(null); + } +};