@btc-vision/transaction 1.1.15 → 1.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/index.js +1 -1
  3. package/browser/keypair/Address.d.ts +2 -0
  4. package/browser/opnet.d.ts +1 -0
  5. package/browser/signer/SignerUtils.d.ts +6 -0
  6. package/browser/transaction/shared/TweakedTransaction.d.ts +5 -6
  7. package/browser/utxo/interfaces/IUTXO.d.ts +1 -0
  8. package/build/_version.d.ts +1 -1
  9. package/build/_version.js +1 -1
  10. package/build/keypair/Address.d.ts +2 -0
  11. package/build/keypair/Address.js +9 -0
  12. package/build/opnet.d.ts +1 -0
  13. package/build/opnet.js +1 -0
  14. package/build/signer/SignerUtils.d.ts +6 -0
  15. package/build/signer/SignerUtils.js +56 -0
  16. package/build/transaction/browser/extensions/UnisatSigner.js +5 -32
  17. package/build/transaction/browser/extensions/XverseSigner.js +5 -48
  18. package/build/transaction/builders/FundingTransaction.js +6 -1
  19. package/build/transaction/builders/TransactionBuilder.js +3 -1
  20. package/build/transaction/shared/TweakedTransaction.d.ts +5 -6
  21. package/build/transaction/shared/TweakedTransaction.js +121 -91
  22. package/build/utils/BitcoinUtils.js +4 -4
  23. package/build/utxo/OPNetLimitedProvider.js +1 -0
  24. package/build/utxo/interfaces/IUTXO.d.ts +1 -0
  25. package/package.json +2 -5
  26. package/src/_version.ts +1 -1
  27. package/src/keypair/Address.ts +15 -0
  28. package/src/opnet.ts +2 -0
  29. package/src/signer/SignerUtils.ts +78 -0
  30. package/src/transaction/TransactionFactory.ts +0 -253
  31. package/src/transaction/browser/extensions/UnisatSigner.ts +4 -40
  32. package/src/transaction/browser/extensions/XverseSigner.ts +9 -68
  33. package/src/transaction/builders/FundingTransaction.ts +7 -2
  34. package/src/transaction/builders/TransactionBuilder.ts +3 -1
  35. package/src/transaction/shared/TweakedTransaction.ts +224 -77
  36. package/src/utils/BitcoinUtils.ts +4 -4
  37. package/src/utxo/OPNetLimitedProvider.ts +1 -0
  38. package/src/utxo/interfaces/IUTXO.ts +2 -0
@@ -9,11 +9,13 @@ export declare class Address extends Uint8Array {
9
9
  static wrap(bytes: ArrayLike<number>): Address;
10
10
  toHex(): string;
11
11
  toBuffer(): Buffer;
12
+ originalPublicKeyBuffer(): Buffer;
12
13
  equals(a: Address): boolean;
13
14
  lessThan(a: Address): boolean;
14
15
  greaterThan(a: Address): boolean;
15
16
  set(publicKey: ArrayLike<number>): void;
16
17
  isValid(network: Network): boolean;
18
+ p2pk(): string;
17
19
  p2wpkh(network: Network): string;
18
20
  p2pkh(network: Network): string;
19
21
  p2shp2wpkh(network: Network): string;
@@ -29,6 +29,7 @@ export * from './transaction/builders/MultiSignTransaction.js';
29
29
  export * from './transaction/builders/SharedInteractionTransaction.js';
30
30
  export * from './transaction/builders/TransactionBuilder.js';
31
31
  export * from './utils/BitcoinUtils.js';
32
+ export * from './utils/lengths.js';
32
33
  export * from './utxo/interfaces/IUTXO.js';
33
34
  export * from './utxo/OPNetLimitedProvider.js';
34
35
  export * from './transaction/processor/PsbtTransaction.js';
@@ -0,0 +1,6 @@
1
+ import { PsbtInput } from '@btc-vision/bitcoin';
2
+ export declare function isTaprootInput(input: PsbtInput): boolean;
3
+ export declare function getInputRelevantScript(input: PsbtInput): Buffer | null;
4
+ export declare function canSignNonTaprootInput(input: PsbtInput, publicKey: Buffer): boolean;
5
+ export declare function pubkeyPositionInScript(pubkey: Buffer, script: Buffer): number;
6
+ export declare function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean;
@@ -48,7 +48,7 @@ export declare abstract class TweakedTransaction extends Logger {
48
48
  protected generateTapData(): Payment;
49
49
  protected generateScriptAddress(): Payment;
50
50
  protected getSignerKey(): Signer | ECPairInterface;
51
- protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean): Promise<void>;
51
+ protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean, errored?: boolean): Promise<void>;
52
52
  protected splitArray<T>(arr: T[], chunkSize: number): T[][];
53
53
  protected signInputs(transaction: Psbt): Promise<void>;
54
54
  protected internalPubKeyToXOnly(): Buffer;
@@ -60,6 +60,10 @@ export declare abstract class TweakedTransaction extends Logger {
60
60
  redeemScript: Buffer;
61
61
  outputScript: Buffer;
62
62
  } | undefined;
63
+ protected generateP2SHP2PKHRedeemScript(inputAddr: string): {
64
+ redeemScript: Buffer;
65
+ outputScript: Buffer;
66
+ } | undefined;
63
67
  protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended;
64
68
  protected customFinalizerP2SH: (inputIndex: number, input: PsbtInput, scriptA: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean) => {
65
69
  finalScriptSig: Buffer | undefined;
@@ -68,11 +72,6 @@ export declare abstract class TweakedTransaction extends Logger {
68
72
  protected signInputsWalletBased(transaction: Psbt): Promise<void>;
69
73
  private attemptSignTaproot;
70
74
  private isTaprootScriptSpend;
71
- private isTaprootInput;
72
- private canSignNonTaprootInput;
73
- private getInputRelevantScript;
74
- private pubkeyInScript;
75
- private pubkeyPositionInScript;
76
75
  private signTaprootInput;
77
76
  private signNonTaprootInput;
78
77
  }
@@ -27,4 +27,5 @@ export interface RawUTXOResponse {
27
27
  readonly outputIndex: number;
28
28
  readonly value: string;
29
29
  readonly scriptPubKey: ScriptPubKey;
30
+ readonly raw: string;
30
31
  }
@@ -1 +1 @@
1
- export declare const version = "1.1.14";
1
+ export declare const version = "1.1.17";
package/build/_version.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.1.14';
1
+ export const version = '1.1.17';
@@ -9,11 +9,13 @@ export declare class Address extends Uint8Array {
9
9
  static wrap(bytes: ArrayLike<number>): Address;
10
10
  toHex(): string;
11
11
  toBuffer(): Buffer;
12
+ originalPublicKeyBuffer(): Buffer;
12
13
  equals(a: Address): boolean;
13
14
  lessThan(a: Address): boolean;
14
15
  greaterThan(a: Address): boolean;
15
16
  set(publicKey: ArrayLike<number>): void;
16
17
  isValid(network: Network): boolean;
18
+ p2pk(): string;
17
19
  p2wpkh(network: Network): string;
18
20
  p2pkh(network: Network): string;
19
21
  p2shp2wpkh(network: Network): string;
@@ -63,6 +63,12 @@ export class Address extends Uint8Array {
63
63
  toBuffer() {
64
64
  return Buffer.from(this);
65
65
  }
66
+ originalPublicKeyBuffer() {
67
+ if (!__classPrivateFieldGet(this, _Address_originalPublicKey, "f")) {
68
+ throw new Error('Public key not set');
69
+ }
70
+ return Buffer.from(__classPrivateFieldGet(this, _Address_originalPublicKey, "f"));
71
+ }
66
72
  equals(a) {
67
73
  const b = this;
68
74
  if (a.length !== b.length) {
@@ -123,6 +129,9 @@ export class Address extends Uint8Array {
123
129
  isValid(network) {
124
130
  return AddressVerificator.isValidPublicKey(Buffer.from(this).toString('hex'), network);
125
131
  }
132
+ p2pk() {
133
+ return this.toHex();
134
+ }
126
135
  p2wpkh(network) {
127
136
  return EcKeyPair.getP2WPKHAddress(this.keyPair, network);
128
137
  }
package/build/opnet.d.ts CHANGED
@@ -29,6 +29,7 @@ export * from './transaction/builders/MultiSignTransaction.js';
29
29
  export * from './transaction/builders/SharedInteractionTransaction.js';
30
30
  export * from './transaction/builders/TransactionBuilder.js';
31
31
  export * from './utils/BitcoinUtils.js';
32
+ export * from './utils/lengths.js';
32
33
  export * from './utxo/interfaces/IUTXO.js';
33
34
  export * from './utxo/OPNetLimitedProvider.js';
34
35
  export * from './transaction/processor/PsbtTransaction.js';
package/build/opnet.js CHANGED
@@ -29,6 +29,7 @@ export * from './transaction/builders/MultiSignTransaction.js';
29
29
  export * from './transaction/builders/SharedInteractionTransaction.js';
30
30
  export * from './transaction/builders/TransactionBuilder.js';
31
31
  export * from './utils/BitcoinUtils.js';
32
+ export * from './utils/lengths.js';
32
33
  export * from './utxo/interfaces/IUTXO.js';
33
34
  export * from './utxo/OPNetLimitedProvider.js';
34
35
  export * from './transaction/processor/PsbtTransaction.js';
@@ -0,0 +1,6 @@
1
+ import { PsbtInput } from '@btc-vision/bitcoin';
2
+ export declare function isTaprootInput(input: PsbtInput): boolean;
3
+ export declare function getInputRelevantScript(input: PsbtInput): Buffer | null;
4
+ export declare function canSignNonTaprootInput(input: PsbtInput, publicKey: Buffer): boolean;
5
+ export declare function pubkeyPositionInScript(pubkey: Buffer, script: Buffer): number;
6
+ export declare function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean;
@@ -0,0 +1,56 @@
1
+ import { crypto as bitCrypto } from '@btc-vision/bitcoin';
2
+ import { isP2TR } from '@btc-vision/bitcoin/src/psbt/psbtutils.js';
3
+ import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
4
+ import * as bscript from '@btc-vision/bitcoin/src/script.js';
5
+ export function isTaprootInput(input) {
6
+ return (input &&
7
+ !!(input.tapInternalKey ||
8
+ input.tapMerkleRoot ||
9
+ (input.tapLeafScript && input.tapLeafScript.length) ||
10
+ (input.tapBip32Derivation && input.tapBip32Derivation.length) ||
11
+ (input.witnessUtxo && isP2TR(input.witnessUtxo.script))));
12
+ }
13
+ export function getInputRelevantScript(input) {
14
+ if (input.redeemScript) {
15
+ return input.redeemScript;
16
+ }
17
+ if (input.witnessScript) {
18
+ return input.witnessScript;
19
+ }
20
+ if (input.witnessUtxo) {
21
+ return input.witnessUtxo.script;
22
+ }
23
+ if (input.nonWitnessUtxo) {
24
+ }
25
+ return null;
26
+ }
27
+ export function canSignNonTaprootInput(input, publicKey) {
28
+ if ((input.nonWitnessUtxo &&
29
+ !input.redeemScript &&
30
+ !input.witnessScript &&
31
+ !input.witnessUtxo) ||
32
+ input.redeemScript) {
33
+ return true;
34
+ }
35
+ const script = getInputRelevantScript(input);
36
+ if (script) {
37
+ return pubkeyInScript(publicKey, script);
38
+ }
39
+ return false;
40
+ }
41
+ export function pubkeyPositionInScript(pubkey, script) {
42
+ const pubkeyHash = bitCrypto.hash160(pubkey);
43
+ const pubkeyXOnly = toXOnly(pubkey);
44
+ const decompiled = bscript.decompile(script);
45
+ if (decompiled === null)
46
+ throw new Error('Unknown script error');
47
+ const a = decompiled.findIndex((element) => {
48
+ if (typeof element === 'number')
49
+ return false;
50
+ return element.equals(pubkey) || element.equals(pubkeyHash) || element.equals(pubkeyXOnly);
51
+ });
52
+ return a;
53
+ }
54
+ export function pubkeyInScript(pubkey, script) {
55
+ return pubkeyPositionInScript(pubkey, script) !== -1;
56
+ }
@@ -1,8 +1,9 @@
1
- import { crypto as bitCrypto, networks, opcodes, Psbt, script as bitScript, } from '@btc-vision/bitcoin';
1
+ import { crypto as bitCrypto, networks, Psbt, script as bitScript, } from '@btc-vision/bitcoin';
2
2
  import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
3
3
  import { CustomKeypair } from '../BrowserSignerBase.js';
4
4
  import { UnisatNetwork } from '../types/Unisat.js';
5
5
  import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
6
+ import { canSignNonTaprootInput, isTaprootInput } from '../../../signer/SignerUtils.js';
6
7
  export class UnisatSigner extends CustomKeypair {
7
8
  constructor() {
8
9
  super();
@@ -147,12 +148,9 @@ export class UnisatSigner extends CustomKeypair {
147
148
  }
148
149
  }
149
150
  }
150
- else {
151
- const script = getInputRelevantScript(input);
152
- if (script && pubkeyInScript(this.publicKey, script)) {
153
- needsToSign = true;
154
- viaTaproot = false;
155
- }
151
+ else if (canSignNonTaprootInput(input, this.publicKey)) {
152
+ needsToSign = true;
153
+ viaTaproot = false;
156
154
  }
157
155
  if (needsToSign) {
158
156
  return {
@@ -248,31 +246,6 @@ export class UnisatSigner extends CustomKeypair {
248
246
  return nonDuplicate;
249
247
  }
250
248
  }
251
- function isTaprootInput(input) {
252
- if (input.tapInternalKey || input.tapKeySig || input.tapScriptSig || input.tapLeafScript) {
253
- return true;
254
- }
255
- if (input.witnessUtxo) {
256
- const script = input.witnessUtxo.script;
257
- return script.length === 34 && script[0] === opcodes.OP_1 && script[1] === 0x20;
258
- }
259
- return false;
260
- }
261
- function getInputRelevantScript(input) {
262
- if (input.redeemScript) {
263
- return input.redeemScript;
264
- }
265
- if (input.witnessScript) {
266
- return input.witnessScript;
267
- }
268
- if (input.witnessUtxo) {
269
- return input.witnessUtxo.script;
270
- }
271
- if (input.nonWitnessUtxo) {
272
- return null;
273
- }
274
- return null;
275
- }
276
249
  function pubkeyInScript(pubkey, script) {
277
250
  return pubkeyPositionInScript(pubkey, script) !== -1;
278
251
  }
@@ -1,7 +1,8 @@
1
- import { crypto as bitCrypto, script as bitScript, networks, opcodes, Psbt, } from '@btc-vision/bitcoin';
1
+ import { networks, Psbt } from '@btc-vision/bitcoin';
2
2
  import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
3
3
  import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
4
4
  import { CustomKeypair } from '../BrowserSignerBase.js';
5
+ import { canSignNonTaprootInput, isTaprootInput, pubkeyInScript, } from '../../../signer/SignerUtils.js';
5
6
  export class XverseSigner extends CustomKeypair {
6
7
  constructor() {
7
8
  super();
@@ -145,12 +146,9 @@ export class XverseSigner extends CustomKeypair {
145
146
  }
146
147
  }
147
148
  }
148
- else {
149
- const script = getInputRelevantScript(input);
150
- if (script && pubkeyInScript(this.publicKey, script)) {
151
- needsToSign = true;
152
- viaTaproot = false;
153
- }
149
+ else if (canSignNonTaprootInput(input, this.publicKey)) {
150
+ needsToSign = true;
151
+ viaTaproot = false;
154
152
  }
155
153
  if (needsToSign) {
156
154
  return {
@@ -256,44 +254,3 @@ export class XverseSigner extends CustomKeypair {
256
254
  return nonDuplicate;
257
255
  }
258
256
  }
259
- function isTaprootInput(input) {
260
- if (input.tapInternalKey || input.tapKeySig || input.tapScriptSig || input.tapLeafScript) {
261
- return true;
262
- }
263
- if (input.witnessUtxo) {
264
- const script = input.witnessUtxo.script;
265
- return script.length === 34 && script[0] === opcodes.OP_1 && script[1] === 0x20;
266
- }
267
- return false;
268
- }
269
- function getInputRelevantScript(input) {
270
- if (input.redeemScript) {
271
- return input.redeemScript;
272
- }
273
- if (input.witnessScript) {
274
- return input.witnessScript;
275
- }
276
- if (input.witnessUtxo) {
277
- return input.witnessUtxo.script;
278
- }
279
- if (input.nonWitnessUtxo) {
280
- return null;
281
- }
282
- return null;
283
- }
284
- function pubkeyInScript(pubkey, script) {
285
- return pubkeyPositionInScript(pubkey, script) !== -1;
286
- }
287
- function pubkeyPositionInScript(pubkey, script) {
288
- const pubkeyHash = bitCrypto.hash160(pubkey);
289
- const pubkeyXOnly = toXOnly(pubkey);
290
- const decompiled = bitScript.decompile(script);
291
- if (decompiled === null)
292
- throw new Error('Unknown script error');
293
- return decompiled.findIndex((element) => {
294
- if (typeof element === 'number')
295
- return false;
296
- return (Buffer.isBuffer(element) &&
297
- (element.equals(pubkey) || element.equals(pubkeyHash) || element.equals(pubkeyXOnly)));
298
- });
299
- }
@@ -1,4 +1,5 @@
1
1
  import { TransactionType } from '../enums/TransactionType.js';
2
+ import { opcodes, script } from '@btc-vision/bitcoin';
2
3
  import { TransactionBuilder } from './TransactionBuilder.js';
3
4
  export class FundingTransaction extends TransactionBuilder {
4
5
  constructor(parameters) {
@@ -17,9 +18,13 @@ export class FundingTransaction extends TransactionBuilder {
17
18
  this.splitInputs(this.amount);
18
19
  }
19
20
  else if (this.isPubKeyDestination) {
21
+ const p2pkScript = script.compile([
22
+ Buffer.from(this.to.replace('0x', ''), 'hex'),
23
+ opcodes.OP_CHECKSIG,
24
+ ]);
20
25
  this.addOutput({
21
26
  value: Number(this.amount),
22
- script: Buffer.from(this.to.slice(2), 'hex'),
27
+ script: p2pkScript,
23
28
  });
24
29
  }
25
30
  else {
@@ -25,7 +25,9 @@ export class TransactionBuilder extends TweakedTransaction {
25
25
  this.priorityFee = parameters.priorityFee ?? 0n;
26
26
  this.utxos = parameters.utxos;
27
27
  this.to = parameters.to || undefined;
28
- this.isPubKeyDestination = this.to ? this.to.startsWith('0x') : false;
28
+ this.isPubKeyDestination = this.to
29
+ ? AddressVerificator.isValidPublicKey(this.to, this.network)
30
+ : false;
29
31
  this.optionalOutputs = parameters.optionalOutputs;
30
32
  this.from = TransactionBuilder.getFrom(parameters.from, this.signer, this.network);
31
33
  this.totalInputAmount = this.calculateTotalUTXOAmount();
@@ -48,7 +48,7 @@ export declare abstract class TweakedTransaction extends Logger {
48
48
  protected generateTapData(): Payment;
49
49
  protected generateScriptAddress(): Payment;
50
50
  protected getSignerKey(): Signer | ECPairInterface;
51
- protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean): Promise<void>;
51
+ protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean, errored?: boolean): Promise<void>;
52
52
  protected splitArray<T>(arr: T[], chunkSize: number): T[][];
53
53
  protected signInputs(transaction: Psbt): Promise<void>;
54
54
  protected internalPubKeyToXOnly(): Buffer;
@@ -60,6 +60,10 @@ export declare abstract class TweakedTransaction extends Logger {
60
60
  redeemScript: Buffer;
61
61
  outputScript: Buffer;
62
62
  } | undefined;
63
+ protected generateP2SHP2PKHRedeemScript(inputAddr: string): {
64
+ redeemScript: Buffer;
65
+ outputScript: Buffer;
66
+ } | undefined;
63
67
  protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended;
64
68
  protected customFinalizerP2SH: (inputIndex: number, input: PsbtInput, scriptA: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean) => {
65
69
  finalScriptSig: Buffer | undefined;
@@ -68,11 +72,6 @@ export declare abstract class TweakedTransaction extends Logger {
68
72
  protected signInputsWalletBased(transaction: Psbt): Promise<void>;
69
73
  private attemptSignTaproot;
70
74
  private isTaprootScriptSpend;
71
- private isTaprootInput;
72
- private canSignNonTaprootInput;
73
- private getInputRelevantScript;
74
- private pubkeyInScript;
75
- private pubkeyPositionInScript;
76
75
  private signTaprootInput;
77
76
  private signNonTaprootInput;
78
77
  }