@btc-vision/transaction 1.6.0 → 1.6.4

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 (49) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/epoch/ChallengeSolution.d.ts +3 -3
  3. package/browser/epoch/validator/EpochValidator.d.ts +5 -6
  4. package/browser/generators/builders/DeploymentGenerator.d.ts +1 -1
  5. package/browser/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
  6. package/browser/index.js +1 -1
  7. package/browser/keypair/AddressVerificator.d.ts +2 -1
  8. package/browser/transaction/TransactionFactory.d.ts +2 -2
  9. package/browser/transaction/builders/DeploymentTransaction.d.ts +1 -1
  10. package/browser/transaction/builders/TransactionBuilder.d.ts +3 -0
  11. package/browser/transaction/interfaces/ITransactionParameters.d.ts +1 -0
  12. package/browser/transaction/shared/TweakedTransaction.d.ts +18 -0
  13. package/browser/utxo/OPNetLimitedProvider.d.ts +0 -4
  14. package/build/_version.d.ts +1 -1
  15. package/build/_version.js +1 -1
  16. package/build/epoch/ChallengeSolution.d.ts +3 -3
  17. package/build/epoch/ChallengeSolution.js +4 -4
  18. package/build/epoch/validator/EpochValidator.d.ts +5 -6
  19. package/build/epoch/validator/EpochValidator.js +16 -17
  20. package/build/generators/builders/DeploymentGenerator.d.ts +1 -1
  21. package/build/generators/builders/DeploymentGenerator.js +5 -5
  22. package/build/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
  23. package/build/generators/builders/LegacyCalldataGenerator.js +2 -2
  24. package/build/keypair/AddressVerificator.d.ts +2 -1
  25. package/build/keypair/AddressVerificator.js +4 -0
  26. package/build/transaction/TransactionFactory.d.ts +2 -2
  27. package/build/transaction/TransactionFactory.js +2 -2
  28. package/build/transaction/builders/DeploymentTransaction.d.ts +1 -1
  29. package/build/transaction/builders/DeploymentTransaction.js +4 -4
  30. package/build/transaction/builders/TransactionBuilder.d.ts +3 -0
  31. package/build/transaction/builders/TransactionBuilder.js +18 -3
  32. package/build/transaction/interfaces/ITransactionParameters.d.ts +1 -0
  33. package/build/transaction/shared/TweakedTransaction.d.ts +18 -0
  34. package/build/transaction/shared/TweakedTransaction.js +135 -18
  35. package/build/utxo/OPNetLimitedProvider.d.ts +0 -4
  36. package/build/utxo/OPNetLimitedProvider.js +0 -7
  37. package/package.json +2 -2
  38. package/src/_version.ts +1 -1
  39. package/src/epoch/ChallengeSolution.ts +10 -10
  40. package/src/epoch/validator/EpochValidator.ts +18 -22
  41. package/src/generators/builders/DeploymentGenerator.ts +6 -6
  42. package/src/generators/builders/LegacyCalldataGenerator.ts +3 -3
  43. package/src/keypair/AddressVerificator.ts +7 -1
  44. package/src/transaction/TransactionFactory.ts +4 -4
  45. package/src/transaction/builders/DeploymentTransaction.ts +5 -5
  46. package/src/transaction/builders/TransactionBuilder.ts +30 -3
  47. package/src/transaction/interfaces/ITransactionParameters.ts +1 -0
  48. package/src/transaction/shared/TweakedTransaction.ts +210 -23
  49. package/src/utxo/OPNetLimitedProvider.ts +0 -17
@@ -28,6 +28,7 @@ initEccLib(ecc);
28
28
 
29
29
  export const MINIMUM_AMOUNT_REWARD: bigint = 540n;
30
30
  export const MINIMUM_AMOUNT_CA: bigint = 297n;
31
+ export const ANCHOR_SCRIPT = Buffer.from('51024e73', 'hex');
31
32
 
32
33
  /**
33
34
  * Allows to build a transaction like you would on Ethereum.
@@ -148,6 +149,12 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
148
149
  */
149
150
  protected isPubKeyDestination: boolean;
150
151
 
152
+ /**
153
+ * @description If the transaction need an anchor output
154
+ * @protected
155
+ */
156
+ protected anchor: boolean;
157
+
151
158
  protected note?: Buffer;
152
159
 
153
160
  protected constructor(parameters: ITransactionParameters) {
@@ -174,6 +181,8 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
174
181
  }
175
182
  }
176
183
 
184
+ this.anchor = parameters.anchor ?? false;
185
+
177
186
  this.isPubKeyDestination = this.to
178
187
  ? AddressVerificator.isValidPublicKey(this.to, this.network)
179
188
  : false;
@@ -191,6 +200,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
191
200
 
192
201
  this.transaction = new Psbt({
193
202
  network: this.network,
203
+ version: this.txVersion,
194
204
  });
195
205
  }
196
206
 
@@ -247,6 +257,13 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
247
257
  });
248
258
  }
249
259
 
260
+ public addAnchor(): void {
261
+ this.addOutput({
262
+ value: 0,
263
+ script: ANCHOR_SCRIPT,
264
+ });
265
+ }
266
+
250
267
  public async getFundingTransactionParameters(): Promise<IFundingTransactionParameters> {
251
268
  if (!this.estimatedFees) {
252
269
  this.estimatedFees = await this.estimateTransactionFees();
@@ -400,8 +417,10 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
400
417
  throw new Error('Output script is too short');
401
418
  }
402
419
 
403
- if (script.script[0] !== opcodes.OP_RETURN) {
404
- throw new Error('Output script must start with OP_RETURN when value is 0');
420
+ if (script.script[0] !== opcodes.OP_RETURN && !script.script.equals(ANCHOR_SCRIPT)) {
421
+ throw new Error(
422
+ 'Output script must start with OP_RETURN or be an ANCHOR when value is 0',
423
+ );
405
424
  }
406
425
  } else if (output.value < TransactionBuilder.MINIMUM_DUST) {
407
426
  throw new Error(
@@ -462,7 +481,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
462
481
  }
463
482
 
464
483
  public async rebuildFromBase64(base64: string): Promise<Psbt> {
465
- this.transaction = Psbt.fromBase64(base64, { network: this.network });
484
+ this.transaction = Psbt.fromBase64(base64, {
485
+ network: this.network,
486
+ version: this.txVersion,
487
+ });
488
+
466
489
  this.signed = false;
467
490
 
468
491
  this.sighashTypes = [Transaction.SIGHASH_ANYONECANPAY, Transaction.SIGHASH_ALL];
@@ -517,6 +540,10 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
517
540
  this.addOPReturn(this.note);
518
541
  }
519
542
 
543
+ if (this.anchor) {
544
+ this.addAnchor();
545
+ }
546
+
520
547
  /** Add the refund output */
521
548
  const sendBackAmount: bigint = this.totalInputAmount - amountSpent;
522
549
  if (sendBackAmount >= TransactionBuilder.MINIMUM_DUST) {
@@ -24,6 +24,7 @@ export interface ITransactionParameters extends ITweakedTransactionData {
24
24
  noSignatures?: boolean;
25
25
 
26
26
  readonly note?: string | Buffer;
27
+ readonly anchor?: boolean;
27
28
 
28
29
  readonly feeRate: number;
29
30
  readonly priorityFee: bigint;
@@ -3,6 +3,7 @@ import {
3
3
  address as bitAddress,
4
4
  crypto as bitCrypto,
5
5
  getFinalScripts,
6
+ isP2A,
6
7
  isP2MS,
7
8
  isP2PK,
8
9
  isP2PKH,
@@ -14,7 +15,6 @@ import {
14
15
  Network,
15
16
  opcodes,
16
17
  P2TRPayment,
17
- Payment,
18
18
  payments,
19
19
  PaymentType,
20
20
  Psbt,
@@ -38,6 +38,9 @@ import {
38
38
  isTaprootInput,
39
39
  pubkeyInScript,
40
40
  } from '../../signer/SignerUtils.js';
41
+ import { TransactionBuilder } from '../builders/TransactionBuilder.js';
42
+
43
+ export type SupportedTransactionVersion = 1 | 2 | 3;
41
44
 
42
45
  export interface ITweakedTransactionData {
43
46
  readonly signer: Signer | ECPairInterface | UnisatSigner;
@@ -46,6 +49,7 @@ export interface ITweakedTransactionData {
46
49
  readonly nonWitnessUtxo?: Buffer;
47
50
  readonly noSignatures?: boolean;
48
51
  readonly unlockScript?: Buffer[];
52
+ readonly txVersion?: SupportedTransactionVersion;
49
53
  }
50
54
 
51
55
  /**
@@ -56,6 +60,13 @@ export enum TransactionSequence {
56
60
  FINAL = 0xffffffff,
57
61
  }
58
62
 
63
+ export enum CSVModes {
64
+ BLOCKS = 0,
65
+ TIMESTAMPS = 1,
66
+ }
67
+
68
+ const CSV_ENABLED_BLOCKS_MASK = 0x3fffffff;
69
+
59
70
  /**
60
71
  * @description PSBT Transaction processor.
61
72
  * */
@@ -88,33 +99,40 @@ export abstract class TweakedTransaction extends Logger {
88
99
  * @protected
89
100
  */
90
101
  protected abstract readonly transaction: Psbt;
102
+
91
103
  /**
92
104
  * @description The sighash types of the transaction
93
105
  * @protected
94
106
  */
95
107
  protected sighashTypes: number[] | undefined;
108
+
96
109
  /**
97
110
  * @description The script data of the transaction
98
111
  */
99
112
  protected scriptData: P2TRPayment | null = null;
113
+
100
114
  /**
101
115
  * @description The tap data of the transaction
102
116
  */
103
117
  protected tapData: P2TRPayment | null = null;
118
+
104
119
  /**
105
120
  * @description The inputs of the transaction
106
121
  */
107
122
  protected readonly inputs: PsbtInputExtended[] = [];
123
+
108
124
  /**
109
125
  * @description The sequence of the transaction
110
126
  * @protected
111
127
  */
112
128
  protected sequence: number = TransactionSequence.REPLACE_BY_FEE;
129
+
113
130
  /**
114
131
  * The tap leaf script
115
132
  * @protected
116
133
  */
117
134
  protected tapLeafScript: TapLeafScript | null = null;
135
+
118
136
  /**
119
137
  * Add a non-witness utxo to the transaction
120
138
  * @protected
@@ -127,11 +145,20 @@ export abstract class TweakedTransaction extends Logger {
127
145
  */
128
146
  protected readonly isBrowser: boolean = false;
129
147
 
148
+ /**
149
+ * Track which inputs contain CSV scripts
150
+ * @protected
151
+ */
152
+ protected csvInputIndices: Set<number> = new Set();
153
+ protected anchorInputIndices: Set<number> = new Set();
154
+
130
155
  protected regenerated: boolean = false;
131
156
  protected ignoreSignatureErrors: boolean = false;
132
157
  protected noSignatures: boolean = false;
133
158
  protected unlockScript: Buffer[] | undefined;
134
159
 
160
+ protected txVersion: SupportedTransactionVersion = 2;
161
+
135
162
  protected constructor(data: ITweakedTransactionData) {
136
163
  super();
137
164
 
@@ -143,6 +170,10 @@ export abstract class TweakedTransaction extends Logger {
143
170
  this.unlockScript = data.unlockScript;
144
171
 
145
172
  this.isBrowser = typeof window !== 'undefined';
173
+
174
+ if (data.txVersion) {
175
+ this.txVersion = data.txVersion;
176
+ }
146
177
  }
147
178
 
148
179
  /**
@@ -303,6 +334,11 @@ export abstract class TweakedTransaction extends Logger {
303
334
  this.sequence = TransactionSequence.FINAL;
304
335
 
305
336
  for (const input of this.inputs) {
337
+ // This would disable CSV! You need to check if the input has CSV
338
+ if (this.csvInputIndices.has(this.inputs.indexOf(input))) {
339
+ continue;
340
+ }
341
+
306
342
  input.sequence = TransactionSequence.FINAL;
307
343
  }
308
344
  }
@@ -402,6 +438,8 @@ export abstract class TweakedTransaction extends Logger {
402
438
  reverse: boolean = false,
403
439
  errored: boolean = false,
404
440
  ): Promise<void> {
441
+ if (this.anchorInputIndices.has(i)) return;
442
+
405
443
  const publicKey = signer.publicKey;
406
444
 
407
445
  let isTaproot = isTaprootInput(input);
@@ -672,7 +710,7 @@ export abstract class TweakedTransaction extends Logger {
672
710
  i: number,
673
711
  _extra: boolean = false,
674
712
  ): PsbtInputExtended {
675
- const script = Buffer.from(utxo.scriptPubKey.hex, 'hex');
713
+ const scriptPub = Buffer.from(utxo.scriptPubKey.hex, 'hex');
676
714
 
677
715
  const input: PsbtInputExtended = {
678
716
  hash: utxo.transactionId,
@@ -680,12 +718,12 @@ export abstract class TweakedTransaction extends Logger {
680
718
  sequence: this.sequence,
681
719
  witnessUtxo: {
682
720
  value: Number(utxo.value),
683
- script,
721
+ script: scriptPub,
684
722
  },
685
723
  };
686
724
 
687
725
  // Handle P2PKH (Legacy)
688
- if (isP2PKH(script)) {
726
+ if (isP2PKH(scriptPub)) {
689
727
  // Legacy input requires nonWitnessUtxo
690
728
  if (utxo.nonWitnessUtxo) {
691
729
  //delete input.witnessUtxo;
@@ -698,28 +736,18 @@ export abstract class TweakedTransaction extends Logger {
698
736
  }
699
737
 
700
738
  // Handle P2WPKH (SegWit)
701
- else if (isP2WPKH(script) || isUnknownSegwitVersion(script)) {
739
+ else if (isP2WPKH(scriptPub) || isUnknownSegwitVersion(scriptPub)) {
702
740
  // No redeemScript required for pure P2WPKH
703
741
  // witnessUtxo is enough, no nonWitnessUtxo needed.
704
742
  }
705
743
 
706
744
  // Handle P2WSH (SegWit)
707
- else if (isP2WSHScript(script)) {
708
- // P2WSH requires a witnessScript
709
- if (!utxo.witnessScript) {
710
- // Can't just invent a witnessScript out of thin air. If not provided, it's an error.
711
- throw new Error('Missing witnessScript for P2WSH UTXO');
712
- }
713
-
714
- input.witnessScript = Buffer.isBuffer(utxo.witnessScript)
715
- ? utxo.witnessScript
716
- : Buffer.from(utxo.witnessScript, 'hex');
717
-
718
- // No nonWitnessUtxo needed for segwit
745
+ else if (isP2WSHScript(scriptPub)) {
746
+ this.processP2WSHInput(utxo, input, i);
719
747
  }
720
748
 
721
749
  // Handle P2SH (Can be legacy or wrapping segwit)
722
- else if (isP2SHScript(script)) {
750
+ else if (isP2SHScript(scriptPub)) {
723
751
  // Redeem script is required for P2SH
724
752
  let redeemScriptBuf: Buffer | undefined;
725
753
 
@@ -771,9 +799,8 @@ export abstract class TweakedTransaction extends Logger {
771
799
  // P2SH-P2WSH
772
800
  // Use witnessUtxo + redeemScript + witnessScript
773
801
  delete input.nonWitnessUtxo; // ensure we do NOT have nonWitnessUtxo
774
- if (!input.witnessScript) {
775
- throw new Error('Missing witnessScript for P2SH-P2WSH UTXO');
776
- }
802
+
803
+ this.processP2WSHInput(utxo, input, i);
777
804
  } else {
778
805
  // Legacy P2SH
779
806
  // Use nonWitnessUtxo
@@ -782,7 +809,7 @@ export abstract class TweakedTransaction extends Logger {
782
809
  }
783
810
 
784
811
  // Handle P2TR (Taproot)
785
- else if (isP2TR(script)) {
812
+ else if (isP2TR(scriptPub)) {
786
813
  // Taproot inputs do not require nonWitnessUtxo, witnessUtxo is sufficient.
787
814
 
788
815
  // If there's a configured sighash type
@@ -796,8 +823,15 @@ export abstract class TweakedTransaction extends Logger {
796
823
  input.tapInternalKey = this.internalPubKeyToXOnly();
797
824
  }
798
825
 
826
+ // Handle P2A (Any SegWit version, future versions)
827
+ else if (isP2A(scriptPub)) {
828
+ this.anchorInputIndices.add(i);
829
+
830
+ input.isPayToAnchor = true;
831
+ }
832
+
799
833
  // Handle P2PK (legacy) or P2MS (bare multisig)
800
- else if (isP2PK(script) || isP2MS(script)) {
834
+ else if (isP2PK(scriptPub) || isP2MS(scriptPub)) {
801
835
  // These are legacy scripts, need nonWitnessUtxo
802
836
  if (utxo.nonWitnessUtxo) {
803
837
  input.nonWitnessUtxo = Buffer.isBuffer(utxo.nonWitnessUtxo)
@@ -836,6 +870,56 @@ export abstract class TweakedTransaction extends Logger {
836
870
  return input;
837
871
  }
838
872
 
873
+ protected processP2WSHInput(utxo: UTXO, input: PsbtInputExtended, i: number): void {
874
+ // P2WSH requires a witnessScript
875
+ if (!utxo.witnessScript) {
876
+ // Can't just invent a witnessScript out of thin air. If not provided, it's an error.
877
+ throw new Error('Missing witnessScript for P2WSH UTXO');
878
+ }
879
+
880
+ input.witnessScript = Buffer.isBuffer(utxo.witnessScript)
881
+ ? utxo.witnessScript
882
+ : Buffer.from(utxo.witnessScript, 'hex');
883
+
884
+ // No nonWitnessUtxo needed for segwit
885
+
886
+ const decompiled = script.decompile(input.witnessScript);
887
+ if (decompiled && this.isCSVScript(decompiled)) {
888
+ const decompiled = script.decompile(input.witnessScript);
889
+ if (decompiled && this.isCSVScript(decompiled)) {
890
+ this.csvInputIndices.add(i);
891
+
892
+ // Extract CSV value from witness script
893
+ const csvBlocks = this.extractCSVBlocks(decompiled);
894
+
895
+ console.log('csvBlocks', csvBlocks);
896
+
897
+ // Use the setCSVSequence method to properly set the sequence
898
+ input.sequence = this.setCSVSequence(csvBlocks, this.sequence);
899
+ }
900
+ }
901
+ }
902
+
903
+ protected secondsToCSVTimeUnits(seconds: number): number {
904
+ return Math.floor(seconds / 512);
905
+ }
906
+
907
+ protected createTimeBasedCSV(seconds: number): number {
908
+ const timeUnits = this.secondsToCSVTimeUnits(seconds);
909
+ if (timeUnits > 0xffff) {
910
+ throw new Error(`Time units ${timeUnits} exceeds maximum of 65,535`);
911
+ }
912
+ return timeUnits | (1 << 22);
913
+ }
914
+
915
+ protected isCSVEnabled(sequence: number): boolean {
916
+ return (sequence & (1 << 31)) === 0;
917
+ }
918
+
919
+ protected extractCSVValue(sequence: number): number {
920
+ return sequence & 0x0000ffff;
921
+ }
922
+
839
923
  protected customFinalizerP2SH = (
840
924
  inputIndex: number,
841
925
  input: PsbtInput,
@@ -858,6 +942,33 @@ export abstract class TweakedTransaction extends Logger {
858
942
  };
859
943
  }
860
944
 
945
+ if (this.anchorInputIndices.has(inputIndex)) {
946
+ return {
947
+ finalScriptSig: undefined,
948
+ finalScriptWitness: Buffer.from([0]),
949
+ };
950
+ }
951
+
952
+ if (isP2WSH && isSegwit && input.witnessScript) {
953
+ if (!input.partialSig || input.partialSig.length === 0) {
954
+ throw new Error(`No signatures for P2WSH input #${inputIndex}`);
955
+ }
956
+
957
+ // Check if this is a CSV input
958
+ const isCSVInput = this.csvInputIndices.has(inputIndex);
959
+ if (isCSVInput) {
960
+ // For CSV P2WSH, the witness stack should be: [signature, witnessScript]
961
+ const witnessStack = [input.partialSig[0].signature, input.witnessScript];
962
+ return {
963
+ finalScriptSig: undefined,
964
+ finalScriptWitness:
965
+ TransactionBuilder.witnessStackToScriptWitness(witnessStack),
966
+ };
967
+ }
968
+
969
+ // For non-CSV P2WSH, use default finalization
970
+ }
971
+
861
972
  return getFinalScripts(
862
973
  inputIndex,
863
974
  input,
@@ -884,6 +995,82 @@ export abstract class TweakedTransaction extends Logger {
884
995
  this.finalized = true;
885
996
  }
886
997
 
998
+ protected isCSVScript(decompiled: (number | Buffer)[]): boolean {
999
+ return decompiled.some((op) => op === opcodes.OP_CHECKSEQUENCEVERIFY);
1000
+ }
1001
+
1002
+ protected setCSVSequence(csvBlocks: number, currentSequence: number): number {
1003
+ if (this.txVersion < 2) {
1004
+ throw new Error('CSV requires transaction version 2 or higher');
1005
+ }
1006
+
1007
+ if (csvBlocks > 0xffff) {
1008
+ throw new Error(`CSV blocks ${csvBlocks} exceeds maximum of 65,535`);
1009
+ }
1010
+
1011
+ // Layout of nSequence field (32 bits) when CSV is active (bit 31 = 0):
1012
+ // Bit 31: Must be 0 (CSV enable flag)
1013
+ // Bits 23-30: Unused by BIP68 (available for custom use)
1014
+ // Bit 22: Time flag (0 = blocks, 1 = time)
1015
+ // Bits 16-21: Unused by BIP68 (available for custom use)
1016
+ // Bits 0-15: CSV lock-time value
1017
+
1018
+ // Extract the time flag if it's set in csvBlocks
1019
+ const isTimeBased = (csvBlocks & (1 << 22)) !== 0;
1020
+
1021
+ // Start with the CSV value
1022
+ let sequence = csvBlocks & 0x0000ffff;
1023
+
1024
+ // Preserve the time flag if set
1025
+ if (isTimeBased) {
1026
+ sequence |= 1 << 22;
1027
+ }
1028
+
1029
+ if (currentSequence === (TransactionSequence.REPLACE_BY_FEE as number)) {
1030
+ // Set bit 25 as our explicit RBF flag
1031
+ // This is in the unused range (bits 23-30) when CSV is active
1032
+ sequence |= 1 << 25;
1033
+
1034
+ // We could use other unused bits for version/features
1035
+ // sequence |= (1 << 26); // Could indicate tx flags if we wanted
1036
+ }
1037
+
1038
+ // Final safety check: ensure bit 31 is 0 (CSV enabled)
1039
+ sequence = sequence & 0x7fffffff;
1040
+
1041
+ return sequence;
1042
+ }
1043
+
1044
+ protected getCSVType(csvValue: number): CSVModes {
1045
+ // Bit 22 determines if it's time-based (1) or block-based (0)
1046
+ return csvValue & (1 << 22) ? CSVModes.TIMESTAMPS : CSVModes.BLOCKS;
1047
+ }
1048
+
1049
+ private extractCSVBlocks(decompiled: (number | Buffer)[]): number {
1050
+ for (let i = 0; i < decompiled.length; i++) {
1051
+ if (decompiled[i] === opcodes.OP_CHECKSEQUENCEVERIFY && i > 0) {
1052
+ const csvValue = decompiled[i - 1];
1053
+ if (Buffer.isBuffer(csvValue)) {
1054
+ return script.number.decode(csvValue);
1055
+ } else if (typeof csvValue === 'number') {
1056
+ // Handle OP_N directly
1057
+ if (csvValue === opcodes.OP_0 || csvValue === opcodes.OP_FALSE) {
1058
+ return 0;
1059
+ } else if (csvValue === opcodes.OP_1NEGATE) {
1060
+ return -1;
1061
+ } else if (csvValue >= opcodes.OP_1 && csvValue <= opcodes.OP_16) {
1062
+ return csvValue - opcodes.OP_1 + 1;
1063
+ } else {
1064
+ // For other numbers, they should have been Buffers
1065
+ // This shouldn't happen in properly decompiled scripts
1066
+ throw new Error(`Unexpected raw number in script: ${csvValue}`);
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+ return 0;
1072
+ }
1073
+
887
1074
  private async attemptSignTaproot(
888
1075
  transaction: Psbt,
889
1076
  input: PsbtInput,
@@ -14,10 +14,6 @@ export interface WalletUTXOs {
14
14
  readonly spentTransactions: RawUTXOResponse[];
15
15
  }
16
16
 
17
- export interface PreimageData {
18
- readonly preimage: Buffer;
19
- }
20
-
21
17
  /**
22
18
  * Allows to fetch UTXO data from any OPNET node
23
19
  */
@@ -181,19 +177,6 @@ export class OPNetLimitedProvider {
181
177
  return result as BroadcastResponse;
182
178
  }
183
179
 
184
- /**
185
- * Fetches the preimage from the OPNET node
186
- * @returns {Promise<PreimageData | undefined>} - The preimage fetched
187
- */
188
- public async getPreimage(): Promise<PreimageData | undefined> {
189
- const result = await this.rpcMethod('btc_preimage', []);
190
- if (!result) {
191
- return;
192
- }
193
-
194
- return result as PreimageData;
195
- }
196
-
197
180
  /**
198
181
  * Splits UTXOs into smaller UTXOs
199
182
  * @param {Wallet} wallet - The wallet to split UTXOs