Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 5 additions & 80 deletions packages/wasm-utxo/js/descriptorWallet/Psbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,22 @@ import {
type WasmBIP32,
type WasmECPair,
type WrapDescriptor,
type PsbtInputData,
type PsbtOutputData,
type PsbtOutputDataWithAddress,
} from "../wasm/wasm_utxo.js";
import type { IPsbt } from "../psbt.js";
import type { PsbtKvKey } from "../fixedScriptWallet/BitGoKeySubtype.js";
import type { CoinName } from "../coinName.js";
import type { BIP32 } from "../bip32.js";
import { Transaction } from "../transaction.js";
import { PsbtBase } from "../psbtBase.js";

export type SignPsbtResult = {
[inputIndex: number]: [pubkey: string][];
};

export class Psbt implements IPsbt {
private _wasm: WasmPsbt;

export class Psbt extends PsbtBase<WasmPsbt> implements IPsbt {
constructor(versionOrWasm?: number | WasmPsbt, lockTime?: number) {
if (versionOrWasm instanceof WasmPsbt) {
this._wasm = versionOrWasm;
} else {
this._wasm = new WasmPsbt(versionOrWasm, lockTime);
}
super(
versionOrWasm instanceof WasmPsbt ? versionOrWasm : new WasmPsbt(versionOrWasm, lockTime),
);
}

/** @internal Access the underlying WASM instance */
Expand All @@ -45,48 +38,12 @@ export class Psbt implements IPsbt {

// -- Serialization --

serialize(): Uint8Array {
return this._wasm.serialize();
}

clone(): Psbt {
return new Psbt(this._wasm.clone());
}

// -- IPsbt: introspection --

inputCount(): number {
return this._wasm.input_count();
}

outputCount(): number {
return this._wasm.output_count();
}

version(): number {
return this._wasm.version();
}

lockTime(): number {
return this._wasm.lock_time();
}

unsignedTxId(): string {
return this._wasm.unsigned_tx_id();
}

getInputs(): PsbtInputData[] {
return this._wasm.get_inputs() as PsbtInputData[];
}

getOutputs(): PsbtOutputData[] {
return this._wasm.get_outputs() as PsbtOutputData[];
}

getGlobalXpubs(): BIP32[] {
return this._wasm.get_global_xpubs() as BIP32[];
}

getOutputsWithAddress(coin: CoinName): PsbtOutputDataWithAddress[] {
return this._wasm.get_outputs_with_address(coin) as PsbtOutputDataWithAddress[];
}
Expand Down Expand Up @@ -122,38 +79,6 @@ export class Psbt implements IPsbt {
return this._wasm.add_output(script, value);
}

removeInput(index: number): void {
this._wasm.remove_input(index);
}

removeOutput(index: number): void {
this._wasm.remove_output(index);
}

setKV(key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_kv(key, value);
}

getKV(key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_kv(key) ?? undefined;
}

setInputKV(index: number, key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_input_kv(index, key, value);
}

getInputKV(index: number, key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_input_kv(index, key) ?? undefined;
}

setOutputKV(index: number, key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_output_kv(index, key, value);
}

getOutputKV(index: number, key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_output_kv(index, key) ?? undefined;
}

// -- Descriptor updates --

updateInputWithDescriptor(inputIndex: number, descriptor: WrapDescriptor): void {
Expand Down
123 changes: 5 additions & 118 deletions packages/wasm-utxo/js/fixedScriptWallet/BitGoPsbt.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import {
BitGoPsbt as WasmBitGoPsbt,
FixedScriptWalletNamespace,
WasmBIP32,
type PsbtInputData,
type PsbtOutputData,
type PsbtOutputDataWithAddress,
} from "../wasm/wasm_utxo.js";
import type { IPsbtWithAddress } from "../psbt.js";
import { PsbtBase } from "../psbtBase.js";
import { type WalletKeysArg, RootWalletKeys } from "./RootWalletKeys.js";
import { type ReplayProtectionArg, ReplayProtection } from "./ReplayProtection.js";
import { type BIP32Arg, BIP32, isBIP32Arg } from "../bip32.js";
import { type ECPairArg, ECPair } from "../ecpair.js";
import type { UtxolibName } from "../utxolibCompat.js";
import type { CoinName } from "../coinName.js";
import type { InputScriptType } from "./scriptType.js";
import type { PsbtKvKey } from "./BitGoKeySubtype.js";
import {
Transaction,
DashTransaction,
Expand Down Expand Up @@ -133,8 +130,10 @@ export type HydrationUnspent = {
value: bigint;
};

export class BitGoPsbt implements IPsbtWithAddress {
protected constructor(protected _wasm: WasmBitGoPsbt) {}
export class BitGoPsbt extends PsbtBase<WasmBitGoPsbt> implements IPsbtWithAddress {
protected constructor(wasm: WasmBitGoPsbt) {
super(wasm);
}

/**
* Get the underlying WASM instance
Expand Down Expand Up @@ -532,64 +531,6 @@ export class BitGoPsbt implements IPsbtWithAddress {
);
}

removeInput(index: number): void {
this._wasm.remove_input(index);
}

removeOutput(index: number): void {
this._wasm.remove_output(index);
}

/**
* Get the unsigned transaction ID
* @returns The unsigned transaction ID
*/
unsignedTxId(): string {
return this._wasm.unsigned_txid();
}

/**
* Get the transaction version
* @returns The transaction version number
*/
version(): number {
return this._wasm.version();
}

lockTime(): number {
return this._wasm.lock_time();
}

/** Set an arbitrary KV pair on the PSBT global map. */
setKV(key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_kv(key, value);
}

/** Get a KV value from the PSBT global map. Returns `undefined` if not present. */
getKV(key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_kv(key) ?? undefined;
}

/** Set an arbitrary KV pair on a specific PSBT input. */
setInputKV(index: number, key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_input_kv(index, key, value);
}

/** Get a KV value from a specific PSBT input. Returns `undefined` if not present. */
getInputKV(index: number, key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_input_kv(index, key) ?? undefined;
}

/** Set an arbitrary KV pair on a specific PSBT output. */
setOutputKV(index: number, key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_output_kv(index, key, value);
}

/** Get a KV value from a specific PSBT output. Returns `undefined` if not present. */
getOutputKV(index: number, key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_output_kv(index, key) ?? undefined;
}

/**
* Parse transaction with wallet keys to identify wallet inputs/outputs
* @param walletKeys - The wallet keys to use for identification
Expand Down Expand Up @@ -850,15 +791,6 @@ export class BitGoPsbt implements IPsbtWithAddress {
return this._wasm.verify_replay_protection_signature(inputIndex, rp.wasm);
}

/**
* Serialize the PSBT to bytes
*
* @returns The serialized PSBT as a byte array
*/
serialize(): Uint8Array {
return this._wasm.serialize();
}

/**
* Generate and store MuSig2 nonces for all MuSig2 inputs
*
Expand Down Expand Up @@ -983,43 +915,6 @@ export class BitGoPsbt implements IPsbtWithAddress {
return this._wasm.extract_half_signed_legacy_tx();
}

/**
* Get the number of inputs in the PSBT
* @returns The number of inputs
*/
inputCount(): number {
return this._wasm.input_count();
}

outputCount(): number {
return this._wasm.output_count();
}

/**
* Get all PSBT inputs as an array
*
* Returns raw PSBT input data including witness_utxo and derivation info.
* For parsed transaction data with address identification, use
* parseTransactionWithWalletKeys() instead.
*
* @returns Array of PsbtInputData objects
*/
getInputs(): PsbtInputData[] {
return this._wasm.get_inputs() as PsbtInputData[];
}

/**
* Get all PSBT outputs as an array
*
* Returns raw PSBT output data without address resolution.
* For output data with addresses, use getOutputsWithAddress().
*
* @returns Array of PsbtOutputData objects
*/
getOutputs(): PsbtOutputData[] {
return this._wasm.get_outputs() as PsbtOutputData[];
}

/**
* Get all PSBT outputs with resolved address strings
*
Expand All @@ -1039,14 +934,6 @@ export class BitGoPsbt implements IPsbtWithAddress {
getOutputsWithAddress(): PsbtOutputDataWithAddress[] {
return this._wasm.get_outputs_with_address() as PsbtOutputDataWithAddress[];
}

/**
* Returns the unordered global xpubs from this PSBT as BIP32 instances.
*/
getGlobalXpubs(): BIP32[] {
const result = this._wasm.get_global_xpubs() as WasmBIP32[];
return result.map((w) => BIP32.fromWasm(w));
}
}

/**
Expand Down
83 changes: 83 additions & 0 deletions packages/wasm-utxo/js/psbtBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import type { PsbtInputData, PsbtOutputData, WasmBIP32 } from "./wasm/wasm_utxo.js";
import { BIP32 } from "./bip32.js";
import type { PsbtKvKey } from "./fixedScriptWallet/BitGoKeySubtype.js";

interface WasmPsbtBase {
input_count(): number;
output_count(): number;
version(): number;
lock_time(): number;
unsigned_tx_id(): string;
serialize(): Uint8Array;
get_inputs(): unknown;
get_outputs(): unknown;
get_global_xpubs(): unknown;
remove_input(index: number): void;
remove_output(index: number): void;
set_kv(key: unknown, value: Uint8Array): void;
get_kv(key: unknown): Uint8Array | null | undefined;
set_input_kv(index: number, key: unknown, value: Uint8Array): void;
get_input_kv(index: number, key: unknown): Uint8Array | null | undefined;
set_output_kv(index: number, key: unknown, value: Uint8Array): void;
get_output_kv(index: number, key: unknown): Uint8Array | null | undefined;
}

export abstract class PsbtBase<W extends WasmPsbtBase> {
protected _wasm: W;

constructor(wasm: W) {
this._wasm = wasm;
}

inputCount(): number {
return this._wasm.input_count();
}
outputCount(): number {
return this._wasm.output_count();
}
version(): number {
return this._wasm.version();
}
lockTime(): number {
return this._wasm.lock_time();
}
unsignedTxId(): string {
return this._wasm.unsigned_tx_id();
}
serialize(): Uint8Array {
return this._wasm.serialize();
}
getInputs(): PsbtInputData[] {
return this._wasm.get_inputs() as PsbtInputData[];
}
getOutputs(): PsbtOutputData[] {
return this._wasm.get_outputs() as PsbtOutputData[];
}
getGlobalXpubs(): BIP32[] {
return (this._wasm.get_global_xpubs() as WasmBIP32[]).map((w) => BIP32.fromWasm(w));
}
removeInput(index: number): void {
this._wasm.remove_input(index);
}
removeOutput(index: number): void {
this._wasm.remove_output(index);
}
setKV(key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_kv(key, value);
}
getKV(key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_kv(key) ?? undefined;
}
setInputKV(index: number, key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_input_kv(index, key, value);
}
getInputKV(index: number, key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_input_kv(index, key) ?? undefined;
}
setOutputKV(index: number, key: PsbtKvKey, value: Uint8Array): void {
this._wasm.set_output_kv(index, key, value);
}
getOutputKV(index: number, key: PsbtKvKey): Uint8Array | undefined {
return this._wasm.get_output_kv(index, key) ?? undefined;
}
}
Loading
Loading