Skip to content
Merged
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
184 changes: 136 additions & 48 deletions packages/wasm-utxo/js/fixedScriptWallet/BitGoPsbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
type PsbtOutputData,
type PsbtOutputDataWithAddress,
} from "../wasm/wasm_utxo.js";
import type { IPsbtIntrospectionWithAddress } from "../psbt.js";
import type { IPsbtWithAddress } from "../psbt.js";
import { type WalletKeysArg, RootWalletKeys } from "./RootWalletKeys.js";
import { type ReplayProtectionArg, ReplayProtection } from "./ReplayProtection.js";
import { type BIP32Arg, BIP32, isBIP32Arg } from "../bip32.js";
Expand Down Expand Up @@ -124,7 +124,7 @@ export type ParseOutputsOptions = {
payGoPubkeys?: ECPairArg[];
};

export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
export class BitGoPsbt implements IPsbtWithAddress {
protected constructor(protected _wasm: WasmBitGoPsbt) {}

/**
Expand Down Expand Up @@ -202,6 +202,45 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
* }, outputScript);
* ```
*/
addInputAtIndex(
index: number,
txid: string,
vout: number,
value: bigint,
script: Uint8Array,
sequence?: number,
): number;
Comment on lines +205 to +212
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a jsdoc here

addInputAtIndex(index: number, options: AddInputOptions, script: Uint8Array): number;
addInputAtIndex(
index: number,
txidOrOptions: string | AddInputOptions,
voutOrScript: number | Uint8Array,
value?: bigint,
script?: Uint8Array,
sequence?: number,
): number {
if (typeof txidOrOptions === "string") {
return this._wasm.add_input_at_index(
index,
txidOrOptions,
voutOrScript as number,
value,
script,
sequence,
);
}
const options = txidOrOptions;
return this._wasm.add_input_at_index(
index,
options.txid,
options.vout,
options.value,
voutOrScript as Uint8Array,
options.sequence,
options.prevTx,
);
}

addInput(options: AddInputOptions, script: Uint8Array): number {
return this._wasm.add_input(
options.txid,
Expand All @@ -225,41 +264,36 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
* const outputIndex = psbt.addOutput(outputScript, 50000n);
* ```
*/
addOutputAtIndex(index: number, script: Uint8Array, value: bigint): number;
addOutputAtIndex(index: number, address: string, value: bigint): number;
addOutputAtIndex(index: number, options: AddOutputOptions): number;
addOutputAtIndex(
index: number,
scriptOrOptions: Uint8Array | string | AddOutputOptions,
value?: bigint,
): number {
if (scriptOrOptions instanceof Uint8Array || typeof scriptOrOptions === "string") {
if (value === undefined) {
throw new Error("Value is required when passing a script or address");
}
if (scriptOrOptions instanceof Uint8Array) {
return this._wasm.add_output_at_index(index, scriptOrOptions, value);
}
return this._wasm.add_output_with_address_at_index(index, scriptOrOptions, value);
}

const options = scriptOrOptions;
if ("script" in options) {
return this._wasm.add_output_at_index(index, options.script, options.value);
}
if ("address" in options) {
return this._wasm.add_output_with_address_at_index(index, options.address, options.value);
}
throw new Error("Invalid output options");
}

addOutput(script: Uint8Array, value: bigint): number;
/**
* Add an output to the PSBT by address
*
* @param address - The destination address
* @param value - Value in satoshis
* @returns The index of the newly added output
*
* @example
* ```typescript
* const outputIndex = psbt.addOutput("bc1q...", 50000n);
* ```
*/
addOutput(address: string, value: bigint): number;
/**
* Add an output to the PSBT
*
* @param options - Output options (script or address, and value)
* @returns The index of the newly added output
*
* @example
* ```typescript
* // Using script
* const outputIndex = psbt.addOutput({
* script: outputScript,
* value: 50000n,
* });
*
* // Using address
* const outputIndex = psbt.addOutput({
* address: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
* value: 50000n,
* });
* ```
*/
addOutput(options: AddOutputOptions): number;
addOutput(scriptOrOptions: Uint8Array | string | AddOutputOptions, value?: bigint): number {
if (scriptOrOptions instanceof Uint8Array || typeof scriptOrOptions === "string") {
Expand Down Expand Up @@ -321,6 +355,28 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
* );
* ```
*/
addWalletInputAtIndex(
index: number,
inputOptions: AddInputOptions,
walletKeys: WalletKeysArg,
walletOptions: AddWalletInputOptions,
): number {
const keys = RootWalletKeys.from(walletKeys);
return this._wasm.add_wallet_input_at_index(
index,
inputOptions.txid,
inputOptions.vout,
inputOptions.value,
keys.wasm,
walletOptions.scriptId.chain,
walletOptions.scriptId.index,
walletOptions.signPath?.signer,
walletOptions.signPath?.cosigner,
inputOptions.sequence,
inputOptions.prevTx,
);
}

addWalletInput(
inputOptions: AddInputOptions,
walletKeys: WalletKeysArg,
Expand Down Expand Up @@ -371,6 +427,21 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
* });
* ```
*/
addWalletOutputAtIndex(
index: number,
walletKeys: WalletKeysArg,
options: AddWalletOutputOptions,
): number {
const keys = RootWalletKeys.from(walletKeys);
return this._wasm.add_wallet_output_at_index(
index,
options.chain,
options.index,
options.value,
keys.wasm,
);
}

addWalletOutput(walletKeys: WalletKeysArg, options: AddWalletOutputOptions): number {
const keys = RootWalletKeys.from(walletKeys);
return this._wasm.add_wallet_output(options.chain, options.index, options.value, keys.wasm);
Expand All @@ -395,6 +466,23 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
* );
* ```
*/
addReplayProtectionInputAtIndex(
index: number,
inputOptions: AddInputOptions,
key: ECPairArg,
): number {
const ecpair = ECPair.from(key);
return this._wasm.add_replay_protection_input_at_index(
index,
ecpair.wasm,
inputOptions.txid,
inputOptions.vout,
inputOptions.value,
inputOptions.sequence,
inputOptions.prevTx,
);
}

addReplayProtectionInput(inputOptions: AddInputOptions, key: ECPairArg): number {
const ecpair = ECPair.from(key);
return this._wasm.add_replay_protection_input(
Expand All @@ -407,27 +495,31 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
);
}

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 {
unsignedTxId(): string {
return this._wasm.unsigned_txid();
}

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

/**
* Get the transaction lock time
* @returns The transaction lock time
*/
get lockTime(): number {
lockTime(): number {
return this._wasm.lock_time();
}

Expand Down Expand Up @@ -828,15 +920,11 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
* Get the number of inputs in the PSBT
* @returns The number of inputs
*/
get inputCount(): number {
inputCount(): number {
return this._wasm.input_count();
}

/**
* Get the number of outputs in the PSBT
* @returns The number of outputs
*/
get outputCount(): number {
outputCount(): number {
return this._wasm.output_count();
}

Expand Down
19 changes: 14 additions & 5 deletions packages/wasm-utxo/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ declare module "./wasm/wasm_utxo.js" {
// Extraction methods
extractTransaction(): WasmTransaction;

// Mutation methods
addInputAtIndex(
index: number,
txid: string,
vout: number,
value: bigint,
script: Uint8Array,
sequence?: number,
): number;
addOutputAtIndex(index: number, script: Uint8Array, value: bigint): number;
removeInput(index: number): void;
removeOutput(index: number): void;

// Metadata methods
unsignedTxId(): string;
lockTime(): number;
Expand All @@ -130,8 +143,4 @@ export { WrapDescriptor as Descriptor } from "./wasm/wasm_utxo.js";
export { WrapMiniscript as Miniscript } from "./wasm/wasm_utxo.js";
export { WrapPsbt as Psbt } from "./wasm/wasm_utxo.js";
export { DashTransaction, Transaction, ZcashTransaction } from "./transaction.js";
export {
hasPsbtMagic,
type IPsbtIntrospection,
type IPsbtIntrospectionWithAddress,
} from "./psbt.js";
export { hasPsbtMagic, type IPsbt, type IPsbtWithAddress } from "./psbt.js";
26 changes: 20 additions & 6 deletions packages/wasm-utxo/js/psbt.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
import type { PsbtInputData, PsbtOutputData, PsbtOutputDataWithAddress } from "./wasm/wasm_utxo.js";

/** Common interface for PSBT introspection methods */
export interface IPsbtIntrospection {
readonly inputCount: number;
readonly outputCount: number;
/** Common interface for PSBT types */
export interface IPsbt {
inputCount(): number;
outputCount(): number;
getInputs(): PsbtInputData[];
getOutputs(): PsbtOutputData[];
version(): number;
lockTime(): number;
unsignedTxId(): string;
addInputAtIndex(
index: number,
txid: string,
vout: number,
value: bigint,
script: Uint8Array,
sequence?: number,
): number;
addOutputAtIndex(index: number, script: Uint8Array, value: bigint): number;
removeInput(index: number): void;
removeOutput(index: number): void;
}

/** Extended introspection with address resolution (no coin parameter needed) */
export interface IPsbtIntrospectionWithAddress extends IPsbtIntrospection {
/** Extended PSBT with address resolution (no coin parameter needed) */
export interface IPsbtWithAddress extends IPsbt {
getOutputsWithAddress(): PsbtOutputDataWithAddress[];
}

Expand Down
14 changes: 8 additions & 6 deletions packages/wasm-utxo/js/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,18 @@ export class Transaction implements ITransaction {
* @param sequence - Optional sequence number (default: 0xFFFFFFFF)
* @returns The index of the newly added input
*/
addInputAtIndex(index: number, txid: string, vout: number, sequence?: number): number {
return this._wasm.add_input_at_index(index, txid, vout, sequence);
}

addInput(txid: string, vout: number, sequence?: number): number {
return this._wasm.add_input(txid, vout, sequence);
}

/**
* Add an output to the transaction
* @param script - Output script (scriptPubKey)
* @param value - Value in satoshis
* @returns The index of the newly added output
*/
addOutputAtIndex(index: number, script: Uint8Array, value: bigint): number {
return this._wasm.add_output_at_index(index, script, value);
}

addOutput(script: Uint8Array, value: bigint): number {
return this._wasm.add_output(script, value);
}
Expand Down
13 changes: 10 additions & 3 deletions packages/wasm-utxo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,16 @@
"build:ts": "npm run build:ts-esm && npm run build:ts-cjs",
"build:package-json": "echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
"build": "npm run build:wasm && npm run build:ts && npm run build:package-json",
"check-fmt": "prettier --check . && cargo fmt -- --check",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
"check-fmt": "npm run lint:prettier && npm run lint:rustfmt",
"lint:prettier": "prettier --check .",
"lint:eslint": "eslint .",
"lint:rustfmt": "cargo fmt -- --check",
"lint:clippy": "cargo clippy --all-targets --all-features -- -D warnings",
"lint": "npm run lint:prettier && npm run lint:eslint && npm run lint:rustfmt && npm run lint:clippy",
"lint:prettier:fix": "prettier --write .",
"lint:eslint:fix": "eslint . --fix",
"lint:rustfmt:fix": "cargo fmt",
"lint:fix": "npm run lint:prettier:fix && npm run lint:eslint:fix && npm run lint:rustfmt:fix"
},
"devDependencies": {
"@bitgo/unspents": "^0.50.13",
Expand Down
Loading