@btc-vision/transaction 1.7.6 → 1.7.10

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 (183) hide show
  1. package/browser/_version.d.ts +1 -0
  2. package/browser/chain/ChainData.d.ts +4 -0
  3. package/browser/{src/deterministic → deterministic}/DeterministicMap.d.ts +3 -3
  4. package/browser/deterministic/FastMap.d.ts +24 -0
  5. package/browser/{src/epoch → epoch}/interfaces/IChallengeSolution.d.ts +4 -4
  6. package/browser/{src/generators → generators}/Features.d.ts +6 -1
  7. package/browser/{src/generators → generators}/Generator.d.ts +1 -0
  8. package/browser/generators/MLDSAData.d.ts +15 -0
  9. package/browser/index.js +1 -1
  10. package/browser/{src/keypair → keypair}/Address.d.ts +9 -3
  11. package/browser/{src/keypair → keypair}/MessageSigner.d.ts +9 -0
  12. package/browser/{src/opnet.d.ts → opnet.d.ts} +2 -1
  13. package/browser/{src/transaction → transaction}/browser/Web3Provider.d.ts +15 -4
  14. package/browser/transaction/browser/types/OPWallet.d.ts +6 -0
  15. package/browser/{src/transaction → transaction}/builders/CustomScriptTransaction.d.ts +1 -0
  16. package/browser/{src/transaction → transaction}/builders/DeploymentTransaction.d.ts +1 -0
  17. package/browser/{src/transaction → transaction}/builders/TransactionBuilder.d.ts +4 -0
  18. package/browser/{src/transaction → transaction}/interfaces/ITransactionParameters.d.ts +3 -0
  19. package/browser/{src/transaction → transaction}/shared/TweakedTransaction.d.ts +6 -0
  20. package/browser/{src/utxo → utxo}/OPNetLimitedProvider.d.ts +1 -0
  21. package/build/_version.d.ts +1 -1
  22. package/build/_version.js +1 -1
  23. package/build/chain/ChainData.d.ts +4 -0
  24. package/build/chain/ChainData.js +20 -0
  25. package/build/deterministic/AddressMap.js +2 -2
  26. package/build/deterministic/DeterministicMap.d.ts +3 -3
  27. package/build/deterministic/DeterministicMap.js +2 -2
  28. package/build/deterministic/FastMap.d.ts +24 -0
  29. package/build/deterministic/{Map.js → FastMap.js} +22 -28
  30. package/build/epoch/ChallengeSolution.js +4 -4
  31. package/build/epoch/interfaces/IChallengeSolution.d.ts +4 -4
  32. package/build/generators/Features.d.ts +6 -1
  33. package/build/generators/Features.js +1 -0
  34. package/build/generators/Generator.d.ts +1 -0
  35. package/build/generators/Generator.js +24 -2
  36. package/build/generators/MLDSAData.d.ts +15 -0
  37. package/build/generators/MLDSAData.js +19 -0
  38. package/build/generators/builders/CalldataGenerator.js +1 -1
  39. package/build/generators/builders/DeploymentGenerator.js +1 -1
  40. package/build/generators/builders/P2WDAGenerator.js +1 -1
  41. package/build/keypair/Address.d.ts +9 -3
  42. package/build/keypair/Address.js +63 -38
  43. package/build/keypair/MessageSigner.d.ts +9 -0
  44. package/build/keypair/MessageSigner.js +101 -3
  45. package/build/opnet.d.ts +2 -1
  46. package/build/opnet.js +2 -1
  47. package/build/transaction/TransactionFactory.js +3 -0
  48. package/build/transaction/browser/Web3Provider.d.ts +15 -4
  49. package/build/transaction/browser/types/OPWallet.d.ts +2 -10
  50. package/build/transaction/browser/types/OPWallet.js +4 -2
  51. package/build/transaction/builders/CustomScriptTransaction.d.ts +1 -0
  52. package/build/transaction/builders/CustomScriptTransaction.js +3 -0
  53. package/build/transaction/builders/DeploymentTransaction.d.ts +1 -0
  54. package/build/transaction/builders/DeploymentTransaction.js +26 -1
  55. package/build/transaction/builders/InteractionTransaction.js +14 -1
  56. package/build/transaction/builders/InteractionTransactionP2WDA.js +14 -1
  57. package/build/transaction/builders/TransactionBuilder.d.ts +4 -0
  58. package/build/transaction/builders/TransactionBuilder.js +77 -0
  59. package/build/transaction/interfaces/ITransactionParameters.d.ts +3 -0
  60. package/build/transaction/shared/P2TR_MS.js +1 -0
  61. package/build/transaction/shared/TweakedTransaction.d.ts +6 -0
  62. package/build/transaction/shared/TweakedTransaction.js +19 -0
  63. package/build/utxo/OPNetLimitedProvider.d.ts +1 -0
  64. package/build/utxo/OPNetLimitedProvider.js +11 -1
  65. package/eslint.config.js +2 -1
  66. package/package.json +1 -1
  67. package/src/_version.ts +1 -1
  68. package/src/chain/ChainData.ts +32 -0
  69. package/src/deterministic/AddressMap.ts +3 -3
  70. package/src/deterministic/DeterministicMap.ts +9 -6
  71. package/src/deterministic/{Map.ts → FastMap.ts} +46 -33
  72. package/src/epoch/ChallengeSolution.ts +4 -4
  73. package/src/epoch/interfaces/IChallengeSolution.ts +4 -4
  74. package/src/generators/Features.ts +8 -2
  75. package/src/generators/Generator.ts +35 -2
  76. package/src/generators/MLDSAData.ts +30 -0
  77. package/src/generators/builders/CalldataGenerator.ts +1 -1
  78. package/src/generators/builders/DeploymentGenerator.ts +2 -1
  79. package/src/generators/builders/LegacyCalldataGenerator.ts +1 -0
  80. package/src/generators/builders/P2WDAGenerator.ts +5 -1
  81. package/src/keypair/Address.ts +78 -38
  82. package/src/keypair/MessageSigner.ts +214 -15
  83. package/src/opnet.ts +3 -1
  84. package/src/transaction/TransactionFactory.ts +3 -0
  85. package/src/transaction/browser/Web3Provider.ts +64 -4
  86. package/src/transaction/browser/types/OPWallet.ts +6 -53
  87. package/src/transaction/builders/CustomScriptTransaction.ts +4 -0
  88. package/src/transaction/builders/DeploymentTransaction.ts +36 -8
  89. package/src/transaction/builders/InteractionTransaction.ts +17 -7
  90. package/src/transaction/builders/InteractionTransactionP2WDA.ts +17 -7
  91. package/src/transaction/builders/TransactionBuilder.ts +107 -0
  92. package/src/transaction/interfaces/ITransactionParameters.ts +12 -0
  93. package/src/transaction/shared/P2TR_MS.ts +1 -0
  94. package/src/transaction/shared/TweakedTransaction.ts +35 -0
  95. package/src/utxo/OPNetLimitedProvider.ts +19 -2
  96. package/test/address.test.ts +18 -20
  97. package/test/addressmap.test.ts +783 -0
  98. package/test/addressverificator-mldsa.test.ts +40 -16
  99. package/test/fastmap-setall.test.ts +143 -0
  100. package/test/fastmap.test.ts +917 -0
  101. package/test/messagesigner-mldsa.test.ts +50 -50
  102. package/test/messagesigner-schnorr.test.ts +40 -40
  103. package/test/old/FastBigIntMap.ts +132 -0
  104. package/test/oldfastmap.test.ts +917 -0
  105. package/tsconfig.webpack.json +2 -6
  106. package/webpack.config.js +1 -1
  107. package/browser/src/_version.d.ts +0 -1
  108. package/browser/src/deterministic/Map.d.ts +0 -19
  109. package/browser/src/transaction/browser/types/OPWallet.d.ts +0 -14
  110. package/browser/test/address.test.d.ts +0 -1
  111. package/browser/test/addressverificator-mldsa.test.d.ts +0 -1
  112. package/browser/test/derivePath.test.d.ts +0 -1
  113. package/browser/test/messagesigner-mldsa.test.d.ts +0 -1
  114. package/browser/test/messagesigner-schnorr.test.d.ts +0 -1
  115. package/browser/test/network-awareness.test.d.ts +0 -1
  116. package/build/deterministic/Map.d.ts +0 -19
  117. /package/browser/{src/abi → abi}/ABICoder.d.ts +0 -0
  118. /package/browser/{src/buffer → buffer}/BinaryReader.d.ts +0 -0
  119. /package/browser/{src/buffer → buffer}/BinaryWriter.d.ts +0 -0
  120. /package/browser/{src/bytecode → bytecode}/Compressor.d.ts +0 -0
  121. /package/browser/{src/consensus → consensus}/Consensus.d.ts +0 -0
  122. /package/browser/{src/consensus → consensus}/ConsensusConfig.d.ts +0 -0
  123. /package/browser/{src/consensus → consensus}/metadata/RoswellConsensus.d.ts +0 -0
  124. /package/browser/{src/crypto → crypto}/crypto-browser.d.ts +0 -0
  125. /package/browser/{src/crypto → crypto}/crypto.d.ts +0 -0
  126. /package/browser/{src/deterministic → deterministic}/AddressMap.d.ts +0 -0
  127. /package/browser/{src/deterministic → deterministic}/AddressSet.d.ts +0 -0
  128. /package/browser/{src/deterministic → deterministic}/CustomMap.d.ts +0 -0
  129. /package/browser/{src/deterministic → deterministic}/DeterministicSet.d.ts +0 -0
  130. /package/browser/{src/epoch → epoch}/ChallengeSolution.d.ts +0 -0
  131. /package/browser/{src/epoch → epoch}/validator/EpochValidator.d.ts +0 -0
  132. /package/browser/{src/event → event}/NetEvent.d.ts +0 -0
  133. /package/browser/{src/generators → generators}/AddressGenerator.d.ts +0 -0
  134. /package/browser/{src/generators → generators}/builders/CalldataGenerator.d.ts +0 -0
  135. /package/browser/{src/generators → generators}/builders/CustomGenerator.d.ts +0 -0
  136. /package/browser/{src/generators → generators}/builders/DeploymentGenerator.d.ts +0 -0
  137. /package/browser/{src/generators → generators}/builders/LegacyCalldataGenerator.d.ts +0 -0
  138. /package/browser/{src/generators → generators}/builders/MultiSignGenerator.d.ts +0 -0
  139. /package/browser/{src/generators → generators}/builders/P2WDAGenerator.d.ts +0 -0
  140. /package/browser/{src/index.d.ts → index.d.ts} +0 -0
  141. /package/browser/{src/keypair → keypair}/AddressVerificator.d.ts +0 -0
  142. /package/browser/{src/keypair → keypair}/EcKeyPair.d.ts +0 -0
  143. /package/browser/{src/keypair → keypair}/Secp256k1PointDeriver.d.ts +0 -0
  144. /package/browser/{src/keypair → keypair}/Wallet.d.ts +0 -0
  145. /package/browser/{src/keypair → keypair}/interfaces/IWallet.d.ts +0 -0
  146. /package/browser/{src/metadata → metadata}/ContractBaseMetadata.d.ts +0 -0
  147. /package/browser/{src/metadata → metadata}/tokens.d.ts +0 -0
  148. /package/browser/{src/mnemonic → mnemonic}/BIPStandard.d.ts +0 -0
  149. /package/browser/{src/mnemonic → mnemonic}/Mnemonic.d.ts +0 -0
  150. /package/browser/{src/mnemonic → mnemonic}/MnemonicStrength.d.ts +0 -0
  151. /package/browser/{src/network → network}/ChainId.d.ts +0 -0
  152. /package/browser/{src/p2wda → p2wda}/P2WDADetector.d.ts +0 -0
  153. /package/browser/{src/signer → signer}/SignerUtils.d.ts +0 -0
  154. /package/browser/{src/signer → signer}/TweakedSigner.d.ts +0 -0
  155. /package/browser/{src/transaction → transaction}/ContractAddress.d.ts +0 -0
  156. /package/browser/{src/transaction → transaction}/TransactionFactory.d.ts +0 -0
  157. /package/browser/{src/transaction → transaction}/browser/BrowserSignerBase.d.ts +0 -0
  158. /package/browser/{src/transaction → transaction}/browser/extensions/UnisatSigner.d.ts +0 -0
  159. /package/browser/{src/transaction → transaction}/browser/extensions/XverseSigner.d.ts +0 -0
  160. /package/browser/{src/transaction → transaction}/browser/types/Unisat.d.ts +0 -0
  161. /package/browser/{src/transaction → transaction}/browser/types/Xverse.d.ts +0 -0
  162. /package/browser/{src/transaction → transaction}/builders/CancelTransaction.d.ts +0 -0
  163. /package/browser/{src/transaction → transaction}/builders/ChallengeSolutionTransaction.d.ts +0 -0
  164. /package/browser/{src/transaction → transaction}/builders/FundingTransaction.d.ts +0 -0
  165. /package/browser/{src/transaction → transaction}/builders/InteractionTransaction.d.ts +0 -0
  166. /package/browser/{src/transaction → transaction}/builders/InteractionTransactionP2WDA.d.ts +0 -0
  167. /package/browser/{src/transaction → transaction}/builders/MultiSignTransaction.d.ts +0 -0
  168. /package/browser/{src/transaction → transaction}/builders/SharedInteractionTransaction.d.ts +0 -0
  169. /package/browser/{src/transaction → transaction}/enums/TransactionType.d.ts +0 -0
  170. /package/browser/{src/transaction → transaction}/interfaces/Tap.d.ts +0 -0
  171. /package/browser/{src/transaction → transaction}/mineable/IP2WSHAddress.d.ts +0 -0
  172. /package/browser/{src/transaction → transaction}/mineable/TimelockGenerator.d.ts +0 -0
  173. /package/browser/{src/transaction → transaction}/processor/PsbtTransaction.d.ts +0 -0
  174. /package/browser/{src/transaction → transaction}/psbt/PSBTTypes.d.ts +0 -0
  175. /package/browser/{src/transaction → transaction}/shared/P2TR_MS.d.ts +0 -0
  176. /package/browser/{src/utils → utils}/BitcoinUtils.d.ts +0 -0
  177. /package/browser/{src/utils → utils}/BufferHelper.d.ts +0 -0
  178. /package/browser/{src/utils → utils}/StringToBuffer.d.ts +0 -0
  179. /package/browser/{src/utils → utils}/lengths.d.ts +0 -0
  180. /package/browser/{src/utils → utils}/types.d.ts +0 -0
  181. /package/browser/{src/utxo → utxo}/interfaces/BroadcastResponse.d.ts +0 -0
  182. /package/browser/{src/utxo → utxo}/interfaces/IUTXO.d.ts +0 -0
  183. /package/browser/{src/verification → verification}/TapscriptVerificator.d.ts +0 -0
@@ -4,6 +4,8 @@ import { crypto, Network, toXOnly } from '@btc-vision/bitcoin';
4
4
  import { TweakedSigner } from '../signer/TweakedSigner.js';
5
5
  import { EcKeyPair } from './EcKeyPair.js';
6
6
  import { MLDSASecurityLevel, QuantumBIP32Interface } from '@btc-vision/bip32';
7
+ import { isOPWallet, OPWallet } from '../transaction/browser/types/OPWallet.js';
8
+ import { MLDSASignature } from '../transaction/browser/Web3Provider.js';
7
9
 
8
10
  export interface SignedMessage {
9
11
  readonly signature: Uint8Array;
@@ -17,27 +19,204 @@ export interface MLDSASignedMessage {
17
19
  readonly securityLevel: MLDSASecurityLevel;
18
20
  }
19
21
 
22
+ interface WindowWithOPWallet {
23
+ opnet?: OPWallet;
24
+ }
25
+
20
26
  class MessageSignerBase {
21
27
  public sha256(message: Buffer | Uint8Array): Buffer {
22
28
  return crypto.sha256(Buffer.from(message));
23
29
  }
24
30
 
31
+ /**
32
+ * Attempts to sign a message using OP_WALLET if available in browser environment.
33
+ * Returns null if not in browser or OP_WALLET is not available.
34
+ * @param {Uint8Array | Buffer | string} message - The message to sign.
35
+ * @returns {Promise<SignedMessage | null>} The Schnorr signature or null if OP_WALLET unavailable.
36
+ */
37
+ public async trySignSchnorrWithOPWallet(
38
+ message: Uint8Array | Buffer | string,
39
+ ): Promise<SignedMessage | null> {
40
+ const wallet = this.getOPWallet();
41
+ if (!wallet) {
42
+ return null;
43
+ }
44
+
45
+ const messageBuffer =
46
+ typeof message === 'string' ? Buffer.from(message, 'utf-8') : Buffer.from(message);
47
+
48
+ const hashedMessage = this.sha256(messageBuffer);
49
+ const messageHex = hashedMessage.toString('hex');
50
+
51
+ const signatureHex = await wallet.web3.signSchnorr(messageHex);
52
+ return {
53
+ signature: Buffer.from(signatureHex, 'hex'),
54
+ message: hashedMessage,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Attempts to sign a message using OP_WALLET ML-DSA if available.
60
+ * Returns null if not in browser or OP_WALLET is not available.
61
+ * @param {Uint8Array | Buffer | string} message - The message to sign.
62
+ * @returns {Promise<MLDSASignedMessage | null>} The ML-DSA signature or null if OP_WALLET unavailable.
63
+ */
64
+ public async trySignMLDSAWithOPWallet(
65
+ message: Uint8Array | Buffer | string,
66
+ ): Promise<MLDSASignedMessage | null> {
67
+ const wallet = this.getOPWallet();
68
+ if (!wallet) {
69
+ return null;
70
+ }
71
+
72
+ const messageBuffer =
73
+ typeof message === 'string' ? Buffer.from(message, 'utf-8') : Buffer.from(message);
74
+
75
+ const hashedMessage = this.sha256(messageBuffer);
76
+ const messageHex = hashedMessage.toString('hex');
77
+
78
+ const result: MLDSASignature = await wallet.web3.signMLDSAMessage(messageHex);
79
+ return {
80
+ signature: Buffer.from(result.signature, 'hex'),
81
+ message: hashedMessage,
82
+ publicKey: Buffer.from(result.publicKey, 'hex'),
83
+ securityLevel: result.securityLevel,
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Signs a message using Schnorr, automatically using OP_WALLET if available and no keypair provided.
89
+ * @param {Uint8Array | Buffer | string} message - The message to sign.
90
+ * @param {ECPairInterface} [keypair] - Optional keypair for local signing.
91
+ * @returns {Promise<SignedMessage>} The Schnorr signature.
92
+ * @throws {Error} If no keypair provided and OP_WALLET is not available.
93
+ */
94
+ public async signMessageAuto(
95
+ message: Uint8Array | Buffer | string,
96
+ keypair?: ECPairInterface,
97
+ ): Promise<SignedMessage> {
98
+ if (!keypair) {
99
+ const walletResult = await this.trySignSchnorrWithOPWallet(message);
100
+ if (walletResult) {
101
+ return walletResult;
102
+ }
103
+ throw new Error('No keypair provided and OP_WALLET is not available.');
104
+ }
105
+
106
+ return this.signMessage(keypair, message);
107
+ }
108
+
109
+ /**
110
+ * Signs a message with tweaking, automatically using OP_WALLET if available.
111
+ * Note: OP_WALLET signSchnorr may already return a tweaked signature depending on wallet implementation.
112
+ * @param {Uint8Array | Buffer | string} message - The message to sign.
113
+ * @param {ECPairInterface} [keypair] - Optional keypair for local signing.
114
+ * @param {Network} [network] - Network required when signing with a local keypair.
115
+ * @returns {Promise<SignedMessage>} The Schnorr signature.
116
+ * @throws {Error} If no keypair provided and OP_WALLET is not available.
117
+ * @throws {Error} If keypair provided but network is missing.
118
+ */
119
+ public async tweakAndSignMessageAuto(
120
+ message: Uint8Array | Buffer | string,
121
+ keypair?: ECPairInterface,
122
+ network?: Network,
123
+ ): Promise<SignedMessage> {
124
+ if (!keypair) {
125
+ const walletResult = await this.trySignSchnorrWithOPWallet(message);
126
+ if (walletResult) {
127
+ return walletResult;
128
+ }
129
+ throw new Error('No keypair provided and OP_WALLET is not available.');
130
+ }
131
+
132
+ if (!network) {
133
+ throw new Error('Network is required when signing with a local keypair.');
134
+ }
135
+
136
+ return this.tweakAndSignMessage(keypair, message, network);
137
+ }
138
+
139
+ /**
140
+ * Signs an ML-DSA message, automatically using OP_WALLET if available.
141
+ * @param {Uint8Array | Buffer | string} message - The message to sign.
142
+ * @param {QuantumBIP32Interface} [mldsaKeypair] - Optional ML-DSA keypair for local signing.
143
+ * @returns {Promise<MLDSASignedMessage>} The ML-DSA signature with metadata.
144
+ * @throws {Error} If no keypair provided and OP_WALLET is not available.
145
+ */
146
+ public async signMLDSAMessageAuto(
147
+ message: Uint8Array | Buffer | string,
148
+ mldsaKeypair?: QuantumBIP32Interface,
149
+ ): Promise<MLDSASignedMessage> {
150
+ if (!mldsaKeypair) {
151
+ const walletResult = await this.trySignMLDSAWithOPWallet(message);
152
+ if (walletResult) {
153
+ return walletResult;
154
+ }
155
+ throw new Error('No ML-DSA keypair provided and OP_WALLET is not available.');
156
+ }
157
+
158
+ return this.signMLDSAMessage(mldsaKeypair, message);
159
+ }
160
+
161
+ /**
162
+ * Verifies an ML-DSA signature using OP_WALLET if available.
163
+ * Returns null if OP_WALLET is not available.
164
+ * @param {Uint8Array | Buffer | string} message - The message to verify.
165
+ * @param {MLDSASignedMessage} signature - The ML-DSA signature to verify.
166
+ * @returns {Promise<boolean | null>} True if valid, false if invalid, null if OP_WALLET unavailable.
167
+ */
168
+ public async verifyMLDSAWithOPWallet(
169
+ message: Uint8Array | Buffer | string,
170
+ signature: MLDSASignedMessage,
171
+ ): Promise<boolean | null> {
172
+ const wallet = this.getOPWallet();
173
+ if (!wallet) {
174
+ return null;
175
+ }
176
+
177
+ const messageBuffer =
178
+ typeof message === 'string' ? Buffer.from(message, 'utf-8') : Buffer.from(message);
179
+
180
+ const hashedMessage = this.sha256(messageBuffer);
181
+
182
+ const mldsaSignature: MLDSASignature = {
183
+ signature: Buffer.from(signature.signature).toString('hex'),
184
+ publicKey: Buffer.from(signature.publicKey).toString('hex'),
185
+ securityLevel: signature.securityLevel,
186
+ messageHash: hashedMessage.toString('hex'),
187
+ };
188
+
189
+ return wallet.web3.verifyMLDSASignature(hashedMessage.toString('hex'), mldsaSignature);
190
+ }
191
+
192
+ /**
193
+ * Gets the ML-DSA public key from OP_WALLET if available.
194
+ * Returns null if OP_WALLET is not available.
195
+ * @returns {Promise<Buffer | null>} The ML-DSA public key or null if OP_WALLET unavailable.
196
+ */
197
+ public async getMLDSAPublicKeyFromOPWallet(): Promise<Buffer | null> {
198
+ const wallet = this.getOPWallet();
199
+ if (!wallet) {
200
+ return null;
201
+ }
202
+
203
+ const publicKeyHex = await wallet.web3.getMLDSAPublicKey();
204
+ return Buffer.from(publicKeyHex, 'hex');
205
+ }
206
+
25
207
  /**
26
208
  * Tweak the keypair and sign a message.
27
209
  * @param {ECPairInterface} keypair - The keypair to sign the message with. Must contain a private key.
28
210
  * @param {Uint8Array | Buffer | string} message - The message to sign.
29
211
  * @param {Network} network - The network to sign the message for.
30
- * @returns The Schnorr signature.
212
+ * @returns {SignedMessage} The Schnorr signature.
31
213
  */
32
214
  public tweakAndSignMessage(
33
215
  keypair: ECPairInterface,
34
216
  message: Uint8Array | Buffer | string,
35
217
  network: Network,
36
218
  ): SignedMessage {
37
- const tweaked = TweakedSigner.tweakSigner(keypair, {
38
- network,
39
- });
40
-
219
+ const tweaked = TweakedSigner.tweakSigner(keypair, { network });
41
220
  return this.signMessage(tweaked, message);
42
221
  }
43
222
 
@@ -45,8 +224,8 @@ class MessageSignerBase {
45
224
  * Signs a message using the provided keypair.
46
225
  * @param {ECPairInterface} keypair - The keypair to sign the message with. Must contain a private key.
47
226
  * @param {Uint8Array | Buffer | string} message - The message to sign.
48
- * @returns The Schnorr signature.
49
- * @throws Error if the private key is missing or invalid.
227
+ * @returns {SignedMessage} The Schnorr signature.
228
+ * @throws {Error} If the private key is missing or invalid.
50
229
  */
51
230
  public signMessage(
52
231
  keypair: ECPairInterface,
@@ -72,8 +251,8 @@ class MessageSignerBase {
72
251
  * @param {Uint8Array | Buffer} publicKey - The public key as a Uint8Array or Buffer.
73
252
  * @param {Uint8Array | Buffer | string} message - The message to verify.
74
253
  * @param {Uint8Array | Buffer} signature - The signature to verify.
75
- * @returns True if the signature is valid, false otherwise.
76
- * @throws Error if the signature length is invalid.
254
+ * @returns {boolean} True if the signature is valid, false otherwise.
255
+ * @throws {Error} If the signature length is invalid.
77
256
  */
78
257
  public verifySignature(
79
258
  publicKey: Uint8Array | Buffer,
@@ -97,8 +276,8 @@ class MessageSignerBase {
97
276
  * @param {Uint8Array | Buffer} publicKey - The public key as a Uint8Array or Buffer.
98
277
  * @param {Uint8Array | Buffer | string} message - The message to verify.
99
278
  * @param {Uint8Array | Buffer} signature - The signature to verify.
100
- * @returns True if the signature is valid, false otherwise.
101
- * @throws Error if the signature length is invalid.
279
+ * @returns {boolean} True if the signature is valid, false otherwise.
280
+ * @throws {Error} If the signature length is invalid.
102
281
  */
103
282
  public tweakAndVerifySignature(
104
283
  publicKey: Uint8Array | Buffer,
@@ -106,7 +285,6 @@ class MessageSignerBase {
106
285
  signature: Uint8Array | Buffer,
107
286
  ): boolean {
108
287
  const tweakedPublicKey = EcKeyPair.tweakPublicKey(Buffer.from(publicKey));
109
-
110
288
  return this.verifySignature(tweakedPublicKey, message, signature);
111
289
  }
112
290
 
@@ -114,8 +292,8 @@ class MessageSignerBase {
114
292
  * Signs a message using ML-DSA signature scheme.
115
293
  * @param {QuantumBIP32Interface} mldsaKeypair - The ML-DSA keypair to sign with. Must contain a private key.
116
294
  * @param {Uint8Array | Buffer | string} message - The message to sign.
117
- * @returns The ML-DSA signature with metadata.
118
- * @throws Error if the private key is missing.
295
+ * @returns {MLDSASignedMessage} The ML-DSA signature with metadata.
296
+ * @throws {Error} If the private key is missing.
119
297
  */
120
298
  public signMLDSAMessage(
121
299
  mldsaKeypair: QuantumBIP32Interface,
@@ -145,7 +323,7 @@ class MessageSignerBase {
145
323
  * @param {QuantumBIP32Interface} mldsaKeypair - The ML-DSA keypair with the public key.
146
324
  * @param {Uint8Array | Buffer | string} message - The message to verify.
147
325
  * @param {Uint8Array | Buffer} signature - The ML-DSA signature to verify.
148
- * @returns True if the signature is valid, false otherwise.
326
+ * @returns {boolean} True if the signature is valid, false otherwise.
149
327
  */
150
328
  public verifyMLDSASignature(
151
329
  mldsaKeypair: QuantumBIP32Interface,
@@ -159,6 +337,27 @@ class MessageSignerBase {
159
337
  const hashedMessage = this.sha256(message);
160
338
  return mldsaKeypair.verify(hashedMessage, signature);
161
339
  }
340
+
341
+ /**
342
+ * Checks if OP_WALLET is available in the current environment.
343
+ * @returns {boolean} True if OP_WALLET is available, false otherwise.
344
+ */
345
+ public isOPWalletAvailable(): boolean {
346
+ return this.getOPWallet() !== null;
347
+ }
348
+
349
+ private getOPWallet(): OPWallet | null {
350
+ if (typeof window === 'undefined') {
351
+ return null;
352
+ }
353
+
354
+ const _window = window as WindowWithOPWallet;
355
+ if (!_window.opnet || !isOPWallet(_window.opnet)) {
356
+ return null;
357
+ }
358
+
359
+ return _window.opnet;
360
+ }
162
361
  }
163
362
 
164
363
  export const MessageSigner = new MessageSignerBase();
package/src/opnet.ts CHANGED
@@ -46,6 +46,8 @@ export {
46
46
  QuantumDerivationPath,
47
47
  } from '@btc-vision/bip32';
48
48
 
49
+ export * from './generators/MLDSAData.js';
50
+
49
51
  /** Metadata */
50
52
  export * from './metadata/ContractBaseMetadata.js';
51
53
  export * from './network/ChainId.js';
@@ -125,7 +127,7 @@ export * from './transaction/browser/Web3Provider.js';
125
127
  export * from './keypair/Secp256k1PointDeriver.js';
126
128
  export * from './transaction/ContractAddress.js';
127
129
 
128
- export * from './deterministic/Map.js';
130
+ export * from './deterministic/FastMap.js';
129
131
  export * from './deterministic/CustomMap.js';
130
132
 
131
133
  declare global {
@@ -188,6 +188,7 @@ export class TransactionFactory {
188
188
  randomBytes: finalTransaction.getRndBytes(),
189
189
  nonWitnessUtxo: signedTransaction.tx.toBuffer(),
190
190
  estimatedFees: finalTransaction.estimatedFees,
191
+ compiledTargetScript: finalTransaction.exportCompiledTargetScript(),
191
192
  optionalInputs: inputs,
192
193
  };
193
194
 
@@ -288,6 +289,7 @@ export class TransactionFactory {
288
289
  utxos: fundingUTXO,
289
290
  randomBytes: finalTransaction.getRndBytes(),
290
291
  challenge: challenge,
292
+ compiledTargetScript: finalTransaction.exportCompiledTargetScript(),
291
293
  nonWitnessUtxo: signedTransaction.tx.toBuffer(),
292
294
  estimatedFees: finalTransaction.estimatedFees,
293
295
  optionalInputs: inputs,
@@ -392,6 +394,7 @@ export class TransactionFactory {
392
394
  ...deploymentParameters,
393
395
  utxos: [newUtxo],
394
396
  randomBytes: finalTransaction.getRndBytes(),
397
+ compiledTargetScript: finalTransaction.exportCompiledTargetScript(),
395
398
  challenge: challenge,
396
399
  nonWitnessUtxo: signedTransaction.toBuffer(),
397
400
  estimatedFees: finalTransaction.estimatedFees,
@@ -6,25 +6,26 @@ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
6
6
  import { CancelledTransaction, DeploymentResult, InteractionResponse } from '../TransactionFactory';
7
7
  import { ICustomTransactionParameters } from '../builders/CustomScriptTransaction.js';
8
8
  import { ICancelTransactionParameters } from '../builders/CancelTransaction.js';
9
+ import { MLDSASecurityLevel } from '@btc-vision/bip32';
9
10
 
10
11
  export type InteractionParametersWithoutSigner = Omit<
11
12
  IInteractionParameters,
12
- 'signer' | 'challenge'
13
+ 'signer' | 'challenge' | 'mldsaSigner'
13
14
  >;
14
15
 
15
16
  export type IDeploymentParametersWithoutSigner = Omit<
16
17
  IDeploymentParameters,
17
- 'signer' | 'network' | 'challenge'
18
+ 'signer' | 'network' | 'challenge' | 'mldsaSigner'
18
19
  >;
19
20
 
20
21
  export type ICustomTransactionWithoutSigner = Omit<
21
22
  ICustomTransactionParameters,
22
- 'signer' | 'challenge'
23
+ 'signer' | 'challenge' | 'mldsaSigner'
23
24
  >;
24
25
 
25
26
  export type ICancelTransactionParametersWithoutSigner = Omit<
26
27
  ICancelTransactionParameters,
27
- 'signer' | 'challenge' | 'network'
28
+ 'signer' | 'challenge' | 'network' | 'mldsaSigner'
28
29
  >;
29
30
 
30
31
  export interface BroadcastTransactionOptions {
@@ -52,6 +53,31 @@ export interface BroadcastedTransaction {
52
53
  readonly peers?: number;
53
54
  }
54
55
 
56
+ /**
57
+ * ML-DSA signature result
58
+ */
59
+ export interface MLDSASignature {
60
+ /**
61
+ * The ML-DSA signature in hex format
62
+ */
63
+ readonly signature: string;
64
+
65
+ /**
66
+ * The ML-DSA public key used for signing in hex format
67
+ */
68
+ readonly publicKey: string;
69
+
70
+ /**
71
+ * The security level used (44, 65, or 87)
72
+ */
73
+ readonly securityLevel: MLDSASecurityLevel;
74
+
75
+ /**
76
+ * The message hash that was signed
77
+ */
78
+ readonly messageHash: string;
79
+ }
80
+
55
81
  export interface Web3Provider {
56
82
  signInteraction(
57
83
  interactionParameters: InteractionParametersWithoutSigner,
@@ -70,4 +96,38 @@ export interface Web3Provider {
70
96
  deployContract(params: IDeploymentParametersWithoutSigner): Promise<DeploymentResult>;
71
97
 
72
98
  broadcast(transactions: BroadcastTransactionOptions[]): Promise<BroadcastedTransaction[]>;
99
+
100
+ /**
101
+ * Sign a message using Schnorr signature
102
+ * @param message - Hexadecimal string message to sign
103
+ * @returns The Schnorr signature in hex format
104
+ * @throws {Error} If signing fails or wallet is not connected
105
+ */
106
+ signSchnorr(message: string): Promise<string>;
107
+
108
+ /**
109
+ * Get the ML-DSA public key for the current account
110
+ *
111
+ * @returns The ML-DSA public key in hex format (never exposes private keys)
112
+ * @throws {Error} If the wallet is not connected
113
+ */
114
+ getMLDSAPublicKey(): Promise<string>;
115
+
116
+ /**
117
+ * Sign a message using ML-DSA signature
118
+ *
119
+ * @param message - The message to sign as a hexadecimal string
120
+ * @returns The ML-DSA signature
121
+ * @throws {Error} If signing fails or wallet is not connected
122
+ */
123
+ signMLDSAMessage(message: string): Promise<MLDSASignature>;
124
+
125
+ /**
126
+ * Verify an ML-DSA signature
127
+ *
128
+ * @param message - The original message, hexadecimal string
129
+ * @param signature - The ML-DSA signature to verify
130
+ * @returns True if the signature is valid
131
+ */
132
+ verifyMLDSASignature(message: string, signature: MLDSASignature): Promise<boolean>;
73
133
  }
@@ -1,30 +1,5 @@
1
1
  import { Unisat } from './Unisat.js';
2
- import { MLDSASecurityLevel } from '@btc-vision/bip32';
3
-
4
- /**
5
- * ML-DSA signature result
6
- */
7
- export interface MLDSASignature {
8
- /**
9
- * The ML-DSA signature in hex format
10
- */
11
- readonly signature: string;
12
-
13
- /**
14
- * The ML-DSA public key used for signing in hex format
15
- */
16
- readonly publicKey: string;
17
-
18
- /**
19
- * The security level used (44, 65, or 87)
20
- */
21
- readonly securityLevel: MLDSASecurityLevel;
22
-
23
- /**
24
- * The message hash that was signed
25
- */
26
- readonly messageHash: string;
27
- }
2
+ import { Web3Provider } from '../Web3Provider.js';
28
3
 
29
4
  /**
30
5
  * OPWallet interface extending Unisat with ML-DSA (FIPS 204) support
@@ -33,31 +8,7 @@ export interface MLDSASignature {
33
8
  * Private keys are NEVER exposed through this interface.
34
9
  */
35
10
  export interface OPWallet extends Unisat {
36
- /**
37
- * Get the ML-DSA public key for the current account
38
- *
39
- * @returns The ML-DSA public key in hex format (never exposes private keys)
40
- * @throws {Error} If the wallet is not connected
41
- */
42
- getMLDSAPublicKey(): Promise<string>;
43
-
44
- /**
45
- * Sign a message using ML-DSA signature
46
- *
47
- * @param message - The message to sign
48
- * @returns The ML-DSA signature
49
- * @throws {Error} If signing fails or wallet is not connected
50
- */
51
- signMLDSAMessage(message: string): Promise<MLDSASignature>;
52
-
53
- /**
54
- * Verify an ML-DSA signature
55
- *
56
- * @param message - The original message
57
- * @param signature - The ML-DSA signature to verify
58
- * @returns True if the signature is valid
59
- */
60
- verifyMLDSASignature(message: string, signature: MLDSASignature): Promise<boolean>;
11
+ web3: Web3Provider;
61
12
  }
62
13
 
63
14
  /**
@@ -67,7 +18,9 @@ export function isOPWallet(wallet: unknown): wallet is OPWallet {
67
18
  return (
68
19
  typeof wallet === 'object' &&
69
20
  wallet !== null &&
70
- 'getMLDSAPublicKey' in wallet &&
71
- 'signMLDSAMessage' in wallet
21
+ 'web3' in wallet &&
22
+ typeof wallet.web3 === 'object' &&
23
+ 'getMLDSAPublicKey' in (wallet.web3 as Web3Provider) &&
24
+ 'signMLDSAMessage' in (wallet.web3 as Web3Provider)
72
25
  );
73
26
  }
@@ -137,6 +137,10 @@ export class CustomScriptTransaction extends TransactionBuilder<TransactionType.
137
137
  return this.to || this.getScriptAddress();
138
138
  }
139
139
 
140
+ public exportCompiledTargetScript(): Buffer {
141
+ return this.compiledTargetScript;
142
+ }
143
+
140
144
  /**
141
145
  * Get the random bytes used for the interaction
142
146
  * @returns {Buffer} The random bytes
@@ -113,6 +113,10 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
113
113
  public constructor(parameters: IDeploymentParameters) {
114
114
  super(parameters);
115
115
 
116
+ if (!this.hashedPublicKey) {
117
+ throw new Error('MLDSA signer must be defined to deploy a contract.');
118
+ }
119
+
116
120
  this.bytecode = Compressor.compress(Buffer.concat([versionBuffer, parameters.bytecode]));
117
121
 
118
122
  this.verifyBytecode();
@@ -142,14 +146,24 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
142
146
  this.network,
143
147
  );
144
148
 
145
- this.compiledTargetScript = this.deploymentGenerator.compile(
146
- this.bytecode,
147
- this.randomBytes,
148
- this.challenge,
149
- this.priorityFee,
150
- this.calldata,
151
- this.generateFeatures(parameters),
152
- );
149
+ if (parameters.compiledTargetScript) {
150
+ if (Buffer.isBuffer(parameters.compiledTargetScript)) {
151
+ this.compiledTargetScript = parameters.compiledTargetScript;
152
+ } else if (typeof parameters.compiledTargetScript === 'string') {
153
+ this.compiledTargetScript = Buffer.from(parameters.compiledTargetScript, 'hex');
154
+ } else {
155
+ throw new Error('Invalid compiled target script format.');
156
+ }
157
+ } else {
158
+ this.compiledTargetScript = this.deploymentGenerator.compile(
159
+ this.bytecode,
160
+ this.randomBytes,
161
+ this.challenge,
162
+ this.priorityFee,
163
+ this.calldata,
164
+ this.generateFeatures(parameters),
165
+ );
166
+ }
153
167
 
154
168
  this.scriptTree = this.getScriptTree();
155
169
 
@@ -180,6 +194,10 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
180
194
  return this.to || this.getScriptAddress();
181
195
  }
182
196
 
197
+ public exportCompiledTargetScript(): Buffer {
198
+ return this.compiledTargetScript;
199
+ }
200
+
183
201
  /**
184
202
  * Get the random bytes used for the interaction
185
203
  * @returns {Buffer} The random bytes
@@ -366,6 +384,16 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
366
384
  });
367
385
  }
368
386
 
387
+ if (parameters.revealMLDSAPublicKey && !parameters.linkMLDSAPublicKeyToAddress) {
388
+ throw new Error(
389
+ 'To reveal the MLDSA public key, you must set linkMLDSAPublicKeyToAddress to true.',
390
+ );
391
+ }
392
+
393
+ if (parameters.linkMLDSAPublicKeyToAddress) {
394
+ this.generateMLDSALinkRequest(parameters, features);
395
+ }
396
+
369
397
  return features;
370
398
  }
371
399
 
@@ -36,13 +36,23 @@ export class InteractionTransaction extends SharedInteractionTransaction<Transac
36
36
  throw new Error('Invalid contract secret length. Expected 32 bytes.');
37
37
  }
38
38
 
39
- this.compiledTargetScript = this.calldataGenerator.compile(
40
- this.calldata,
41
- this.contractSecret,
42
- this.challenge,
43
- this.priorityFee,
44
- this.generateFeatures(parameters),
45
- );
39
+ if (parameters.compiledTargetScript) {
40
+ if (Buffer.isBuffer(parameters.compiledTargetScript)) {
41
+ this.compiledTargetScript = parameters.compiledTargetScript;
42
+ } else if (typeof parameters.compiledTargetScript === 'string') {
43
+ this.compiledTargetScript = Buffer.from(parameters.compiledTargetScript, 'hex');
44
+ } else {
45
+ throw new Error('Invalid compiled target script format.');
46
+ }
47
+ } else {
48
+ this.compiledTargetScript = this.calldataGenerator.compile(
49
+ this.calldata,
50
+ this.contractSecret,
51
+ this.challenge,
52
+ this.priorityFee,
53
+ this.generateFeatures(parameters),
54
+ );
55
+ }
46
56
 
47
57
  this.scriptTree = this.getScriptTree();
48
58
  this.internalInit();
@@ -97,13 +97,23 @@ export class InteractionTransactionP2WDA extends TransactionBuilder<TransactionT
97
97
  // Validate P2WDA inputs
98
98
  this.validateP2WDAInputs();
99
99
 
100
- this.compiledOperationData = this.p2wdaGenerator.compile(
101
- this.calldata,
102
- this.contractSecret,
103
- this.challenge,
104
- this.priorityFee,
105
- this.generateFeatures(parameters),
106
- );
100
+ if (parameters.compiledTargetScript) {
101
+ if (Buffer.isBuffer(parameters.compiledTargetScript)) {
102
+ this.compiledOperationData = parameters.compiledTargetScript;
103
+ } else if (typeof parameters.compiledTargetScript === 'string') {
104
+ this.compiledOperationData = Buffer.from(parameters.compiledTargetScript, 'hex');
105
+ } else {
106
+ throw new Error('Invalid compiled target script format.');
107
+ }
108
+ } else {
109
+ this.compiledOperationData = this.p2wdaGenerator.compile(
110
+ this.calldata,
111
+ this.contractSecret,
112
+ this.challenge,
113
+ this.priorityFee,
114
+ this.generateFeatures(parameters),
115
+ );
116
+ }
107
117
 
108
118
  // Validate size early
109
119
  this.validateOperationDataSize();