@btc-vision/bitcoin 7.0.0-beta.0 → 7.0.0-beta.1
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.
- package/README.md +112 -13
- package/benchmark-compare/BENCHMARK.md +74 -59
- package/benchmark-compare/compare.bench.ts +249 -96
- package/benchmark-compare/harness.ts +23 -25
- package/benchmark-compare/package.json +1 -0
- package/browser/address.d.ts +4 -4
- package/browser/address.d.ts.map +1 -1
- package/browser/chunks/{psbt-parallel-B-dfm5GZ.js → psbt-parallel-jZ6QcCnM.js} +3128 -2731
- package/browser/index.d.ts +1 -1
- package/browser/index.d.ts.map +1 -1
- package/browser/index.js +603 -585
- package/browser/io/base58check.d.ts +1 -25
- package/browser/io/base58check.d.ts.map +1 -1
- package/browser/io/base64.d.ts.map +1 -1
- package/browser/networks.d.ts +1 -0
- package/browser/networks.d.ts.map +1 -1
- package/browser/payments/bip341.d.ts +17 -0
- package/browser/payments/bip341.d.ts.map +1 -1
- package/browser/payments/index.d.ts +3 -2
- package/browser/payments/index.d.ts.map +1 -1
- package/browser/payments/p2mr.d.ts +169 -0
- package/browser/payments/p2mr.d.ts.map +1 -0
- package/browser/payments/types.d.ts +11 -1
- package/browser/payments/types.d.ts.map +1 -1
- package/browser/psbt/bip371.d.ts +30 -0
- package/browser/psbt/bip371.d.ts.map +1 -1
- package/browser/psbt/psbtutils.d.ts +1 -0
- package/browser/psbt/psbtutils.d.ts.map +1 -1
- package/browser/psbt.d.ts.map +1 -1
- package/browser/workers/index.js +9 -9
- package/build/address.d.ts +4 -4
- package/build/address.d.ts.map +1 -1
- package/build/address.js +11 -1
- package/build/address.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/io/base58check.d.ts +1 -25
- package/build/io/base58check.d.ts.map +1 -1
- package/build/io/base58check.js +1 -31
- package/build/io/base58check.js.map +1 -1
- package/build/io/base64.d.ts.map +1 -1
- package/build/io/base64.js +3 -0
- package/build/io/base64.js.map +1 -1
- package/build/networks.d.ts +1 -0
- package/build/networks.d.ts.map +1 -1
- package/build/networks.js +12 -0
- package/build/networks.js.map +1 -1
- package/build/payments/bip341.d.ts +17 -0
- package/build/payments/bip341.d.ts.map +1 -1
- package/build/payments/bip341.js +32 -1
- package/build/payments/bip341.js.map +1 -1
- package/build/payments/index.d.ts +3 -2
- package/build/payments/index.d.ts.map +1 -1
- package/build/payments/index.js +2 -1
- package/build/payments/index.js.map +1 -1
- package/build/payments/p2mr.d.ts +178 -0
- package/build/payments/p2mr.d.ts.map +1 -0
- package/build/payments/p2mr.js +555 -0
- package/build/payments/p2mr.js.map +1 -0
- package/build/payments/types.d.ts +11 -1
- package/build/payments/types.d.ts.map +1 -1
- package/build/payments/types.js +1 -0
- package/build/payments/types.js.map +1 -1
- package/build/psbt/bip371.d.ts +30 -0
- package/build/psbt/bip371.d.ts.map +1 -1
- package/build/psbt/bip371.js +80 -15
- package/build/psbt/bip371.js.map +1 -1
- package/build/psbt/psbtutils.d.ts +1 -0
- package/build/psbt/psbtutils.d.ts.map +1 -1
- package/build/psbt/psbtutils.js +2 -0
- package/build/psbt/psbtutils.js.map +1 -1
- package/build/psbt.d.ts.map +1 -1
- package/build/psbt.js +3 -2
- package/build/psbt.js.map +1 -1
- package/build/pubkey.js +1 -1
- package/build/pubkey.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/documentation/README.md +122 -0
- package/documentation/address.md +820 -0
- package/documentation/block.md +679 -0
- package/documentation/crypto.md +461 -0
- package/documentation/ecc.md +584 -0
- package/documentation/errors.md +656 -0
- package/documentation/io.md +942 -0
- package/documentation/networks.md +625 -0
- package/documentation/p2mr.md +380 -0
- package/documentation/payments.md +1485 -0
- package/documentation/psbt.md +1400 -0
- package/documentation/script.md +730 -0
- package/documentation/taproot.md +670 -0
- package/documentation/transaction.md +943 -0
- package/documentation/types.md +587 -0
- package/documentation/workers.md +1007 -0
- package/eslint.config.js +3 -0
- package/package.json +17 -14
- package/src/address.ts +22 -10
- package/src/index.ts +1 -0
- package/src/io/base58check.ts +1 -35
- package/src/io/base64.ts +5 -0
- package/src/networks.ts +13 -0
- package/src/payments/bip341.ts +36 -1
- package/src/payments/index.ts +4 -0
- package/src/payments/p2mr.ts +660 -0
- package/src/payments/types.ts +12 -0
- package/src/psbt/bip371.ts +84 -13
- package/src/psbt/psbtutils.ts +2 -0
- package/src/psbt.ts +4 -2
- package/src/pubkey.ts +1 -1
- package/test/bitcoin.core.spec.ts +1 -1
- package/test/fixtures/p2mr.json +270 -0
- package/test/integration/taproot.spec.ts +7 -3
- package/test/opnetTestnet.spec.ts +302 -0
- package/test/payments.spec.ts +3 -1
- package/test/psbt.spec.ts +297 -2
- package/test/tsconfig.json +2 -2
|
@@ -0,0 +1,1485 @@
|
|
|
1
|
+
# Payments Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for all Bitcoin payment types in the `@btc-vision/bitcoin` library.
|
|
4
|
+
|
|
5
|
+
Each payment type is implemented as a class with lazy-computed getters, static factory methods, and a legacy factory function for backwards compatibility.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
| Payment Type | Full Name | Class | Factory | Address Format | SegWit Version | BIP |
|
|
12
|
+
|---|---|---|---|---|---|---|
|
|
13
|
+
| P2PK | Pay-to-Public-Key | `P2PK` | `p2pk()` | None | N/A (legacy) | - |
|
|
14
|
+
| P2PKH | Pay-to-Public-Key-Hash | `P2PKH` | `p2pkh()` | `1...` (Base58Check) | N/A (legacy) | - |
|
|
15
|
+
| P2SH | Pay-to-Script-Hash | `P2SH` | `p2sh()` | `3...` (Base58Check) | N/A (legacy) | 16 |
|
|
16
|
+
| P2MS | Pay-to-Multisig | `P2MS` | `p2ms()` | None | N/A (legacy) | 11 |
|
|
17
|
+
| P2WPKH | Pay-to-Witness-Public-Key-Hash | `P2WPKH` | `p2wpkh()` | `bc1q...` (bech32) | 0 | 141 |
|
|
18
|
+
| P2WSH | Pay-to-Witness-Script-Hash | `P2WSH` | `p2wsh()` | `bc1q...` (bech32) | 0 | 141 |
|
|
19
|
+
| P2TR | Pay-to-Taproot | `P2TR` | `p2tr()` | `bc1p...` (bech32m) | 1 | 341 |
|
|
20
|
+
| P2MR | Pay-to-Merkle-Root | `P2MR` | `p2mr()` | `bc1z...` (bech32m) | 2 | 360 |
|
|
21
|
+
| P2OP | Pay-to-OPNet | `P2OP` | `p2op()` | bech32m (custom prefix) | 16 | - |
|
|
22
|
+
| Embed | OP_RETURN Data | `Embed` | `p2data()` | None | N/A | - |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Import
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import {
|
|
30
|
+
// Types and interfaces
|
|
31
|
+
PaymentType,
|
|
32
|
+
type BasePayment,
|
|
33
|
+
type ScriptRedeem,
|
|
34
|
+
type Payment,
|
|
35
|
+
type PaymentCreator,
|
|
36
|
+
type PaymentOpts,
|
|
37
|
+
|
|
38
|
+
// Payment classes and factory functions
|
|
39
|
+
P2PK, p2pk,
|
|
40
|
+
P2PKH, p2pkh,
|
|
41
|
+
P2SH, p2sh,
|
|
42
|
+
P2MS, p2ms,
|
|
43
|
+
P2WPKH, p2wpkh,
|
|
44
|
+
P2WSH, p2wsh,
|
|
45
|
+
P2TR, p2tr,
|
|
46
|
+
P2MR, p2mr,
|
|
47
|
+
P2OP, p2op,
|
|
48
|
+
Embed, p2data,
|
|
49
|
+
|
|
50
|
+
// Individual payment type interfaces
|
|
51
|
+
type P2PKPayment,
|
|
52
|
+
type P2PKHPayment,
|
|
53
|
+
type P2SHPayment,
|
|
54
|
+
type P2MSPayment,
|
|
55
|
+
type P2WPKHPayment,
|
|
56
|
+
type P2WSHPayment,
|
|
57
|
+
type P2TRPayment,
|
|
58
|
+
type P2MRPayment,
|
|
59
|
+
type P2OPPayment,
|
|
60
|
+
type P2OPPaymentParams,
|
|
61
|
+
type EmbedPayment,
|
|
62
|
+
|
|
63
|
+
// BIP341 Taproot utilities
|
|
64
|
+
findScriptPath,
|
|
65
|
+
LEAF_VERSION_TAPSCRIPT,
|
|
66
|
+
MAX_TAPTREE_DEPTH,
|
|
67
|
+
rootHashFromPath,
|
|
68
|
+
rootHashFromPathP2MR,
|
|
69
|
+
tapBranchHash,
|
|
70
|
+
tapleafHash,
|
|
71
|
+
toHashTree,
|
|
72
|
+
tweakKey,
|
|
73
|
+
type HashTree,
|
|
74
|
+
} from '@btc-vision/bitcoin';
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## PaymentType Enum
|
|
80
|
+
|
|
81
|
+
`PaymentType` is a const object used as a discriminant for the `Payment` union type. Each payment class returns its corresponding `PaymentType` value from the `name` getter.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const PaymentType = {
|
|
85
|
+
P2PK: 'p2pk',
|
|
86
|
+
P2PKH: 'p2pkh',
|
|
87
|
+
P2SH: 'p2sh',
|
|
88
|
+
P2MS: 'p2ms',
|
|
89
|
+
P2WPKH: 'p2wpkh',
|
|
90
|
+
P2WSH: 'p2wsh',
|
|
91
|
+
P2TR: 'p2tr',
|
|
92
|
+
P2MR: 'p2mr',
|
|
93
|
+
P2OP: 'p2op',
|
|
94
|
+
Embed: 'embed',
|
|
95
|
+
ScriptRedeem: 'scriptRedeem',
|
|
96
|
+
} as const;
|
|
97
|
+
|
|
98
|
+
type PaymentType = (typeof PaymentType)[keyof typeof PaymentType];
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Common Interfaces
|
|
104
|
+
|
|
105
|
+
### BasePayment
|
|
106
|
+
|
|
107
|
+
The base interface shared by all payment types.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
interface BasePayment {
|
|
111
|
+
readonly name?: string | undefined;
|
|
112
|
+
readonly network?: Network | undefined;
|
|
113
|
+
readonly output?: Script | undefined;
|
|
114
|
+
readonly input?: Script | undefined;
|
|
115
|
+
readonly address?: string | undefined;
|
|
116
|
+
readonly witness?: Uint8Array[] | undefined;
|
|
117
|
+
readonly redeem?: ScriptRedeem | undefined;
|
|
118
|
+
readonly useHybrid?: boolean | undefined;
|
|
119
|
+
readonly useUncompressed?: boolean | undefined;
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
| Property | Type | Description |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `name` | `string` | Discriminant label for the union type (e.g., `'p2pkh'`, `'p2tr'`). |
|
|
126
|
+
| `network` | `Network` | Network parameters (mainnet if omitted). |
|
|
127
|
+
| `output` | `Script` | Fully-assembled scriptPubKey. |
|
|
128
|
+
| `input` | `Script` | Raw scriptSig (legacy types only). |
|
|
129
|
+
| `address` | `string` | Human-readable address. |
|
|
130
|
+
| `witness` | `Uint8Array[]` | SegWit witness stack (empty for legacy). |
|
|
131
|
+
| `redeem` | `ScriptRedeem` | Script template for P2SH, P2WSH, P2TR, etc. |
|
|
132
|
+
| `useHybrid` | `boolean` | Use hybrid public key format (non-standard). |
|
|
133
|
+
| `useUncompressed` | `boolean` | Use uncompressed public key format (non-standard). |
|
|
134
|
+
|
|
135
|
+
### ScriptRedeem
|
|
136
|
+
|
|
137
|
+
Helper interface used by redeeming script-template outputs (P2SH, P2WSH, P2TR, P2MR).
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
interface ScriptRedeem extends BasePayment {
|
|
141
|
+
readonly output?: Script | undefined;
|
|
142
|
+
readonly redeemVersion?: number | undefined;
|
|
143
|
+
readonly network?: Network | undefined;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### PaymentOpts
|
|
148
|
+
|
|
149
|
+
Options passed to constructors and factory functions.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
interface PaymentOpts {
|
|
153
|
+
readonly validate?: boolean; // Validate inputs (default: true)
|
|
154
|
+
readonly allowIncomplete?: boolean; // Allow incomplete signatures (default: false)
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### PaymentCreator
|
|
159
|
+
|
|
160
|
+
Generic factory function type.
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
type PaymentCreator = <T extends BasePayment>(a: T, opts?: PaymentOpts) => T;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Payment (Union Type)
|
|
167
|
+
|
|
168
|
+
The discriminated union of all payment types.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
type Payment =
|
|
172
|
+
| P2PKPayment
|
|
173
|
+
| P2PKHPayment
|
|
174
|
+
| P2SHPayment
|
|
175
|
+
| P2MSPayment
|
|
176
|
+
| P2WPKHPayment
|
|
177
|
+
| P2WSHPayment
|
|
178
|
+
| P2TRPayment
|
|
179
|
+
| P2MRPayment
|
|
180
|
+
| P2OPPayment
|
|
181
|
+
| EmbedPayment
|
|
182
|
+
| ScriptRedeem;
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## P2PK (Pay-to-Public-Key)
|
|
188
|
+
|
|
189
|
+
P2PK is the simplest Bitcoin payment type. The output script contains a public key directly, and spending requires a single signature from that key. P2PK has no address format.
|
|
190
|
+
|
|
191
|
+
### Overview
|
|
192
|
+
|
|
193
|
+
| Property | Value |
|
|
194
|
+
|----------|-------|
|
|
195
|
+
| SegWit version | N/A (legacy) |
|
|
196
|
+
| Address format | None |
|
|
197
|
+
| Script size | 35 bytes (compressed) or 67 bytes (uncompressed) |
|
|
198
|
+
|
|
199
|
+
### Script Structure
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
Output: {pubKey} OP_CHECKSIG
|
|
203
|
+
Input: {signature}
|
|
204
|
+
Witness: [] (empty)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Class: P2PK
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
class P2PK {
|
|
211
|
+
static readonly NAME = 'p2pk';
|
|
212
|
+
|
|
213
|
+
constructor(params: {
|
|
214
|
+
pubkey?: Uint8Array;
|
|
215
|
+
signature?: Uint8Array;
|
|
216
|
+
output?: Uint8Array;
|
|
217
|
+
input?: Uint8Array;
|
|
218
|
+
network?: Network;
|
|
219
|
+
}, opts?: PaymentOpts);
|
|
220
|
+
|
|
221
|
+
// Getters
|
|
222
|
+
get name(): 'p2pk';
|
|
223
|
+
get network(): Network;
|
|
224
|
+
get pubkey(): PublicKey | undefined;
|
|
225
|
+
get signature(): Signature | undefined;
|
|
226
|
+
get output(): Script | undefined;
|
|
227
|
+
get input(): Script | undefined;
|
|
228
|
+
get witness(): Uint8Array[] | undefined;
|
|
229
|
+
|
|
230
|
+
// Static factory methods
|
|
231
|
+
static fromPubkey(pubkey: PublicKey, network?: Network): P2PK;
|
|
232
|
+
static fromOutput(output: Uint8Array, network?: Network): P2PK;
|
|
233
|
+
static fromSignature(signature: Signature, pubkey?: PublicKey, network?: Network): P2PK;
|
|
234
|
+
|
|
235
|
+
toPayment(): P2PKPayment;
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Factory Function
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
function p2pk(a: Omit<P2PKPayment, 'name'>, opts?: PaymentOpts): P2PKPayment;
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### P2PKPayment Interface
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
interface P2PKPayment extends BasePayment {
|
|
249
|
+
readonly name: 'p2pk';
|
|
250
|
+
readonly pubkey?: PublicKey | undefined;
|
|
251
|
+
readonly signature?: Signature | undefined;
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Examples
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { P2PK, p2pk } from '@btc-vision/bitcoin';
|
|
259
|
+
|
|
260
|
+
// Create from public key (class)
|
|
261
|
+
const payment = P2PK.fromPubkey(pubkey);
|
|
262
|
+
console.log(payment.output); // {pubKey} OP_CHECKSIG
|
|
263
|
+
|
|
264
|
+
// Create from output script (class)
|
|
265
|
+
const decoded = P2PK.fromOutput(scriptPubKey);
|
|
266
|
+
console.log(decoded.pubkey); // extracted public key
|
|
267
|
+
|
|
268
|
+
// Create from signature for spending
|
|
269
|
+
const spender = P2PK.fromSignature(signature, pubkey);
|
|
270
|
+
console.log(spender.input); // {signature}
|
|
271
|
+
|
|
272
|
+
// Legacy factory function
|
|
273
|
+
const legacy = p2pk({ pubkey });
|
|
274
|
+
console.log(legacy.output);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## P2PKH (Pay-to-Public-Key-Hash)
|
|
280
|
+
|
|
281
|
+
P2PKH is the most common legacy Bitcoin payment type. The output script contains the hash of a public key, and spending requires both the full public key and a valid signature. Addresses start with `1` on mainnet.
|
|
282
|
+
|
|
283
|
+
### Overview
|
|
284
|
+
|
|
285
|
+
| Property | Value |
|
|
286
|
+
|----------|-------|
|
|
287
|
+
| SegWit version | N/A (legacy) |
|
|
288
|
+
| Address format | Base58Check (`1...` mainnet, `m...`/`n...` testnet) |
|
|
289
|
+
| Hash algorithm | RIPEMD160(SHA256(pubkey)) = 20 bytes |
|
|
290
|
+
| Script size | 25 bytes |
|
|
291
|
+
|
|
292
|
+
### Script Structure
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
Output: OP_DUP OP_HASH160 {hash160(pubkey)} OP_EQUALVERIFY OP_CHECKSIG
|
|
296
|
+
Input: {signature} {pubkey}
|
|
297
|
+
Witness: [] (empty)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Class: P2PKH
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
class P2PKH {
|
|
304
|
+
static readonly NAME = 'p2pkh';
|
|
305
|
+
|
|
306
|
+
constructor(params: {
|
|
307
|
+
address?: string;
|
|
308
|
+
hash?: Uint8Array;
|
|
309
|
+
pubkey?: Uint8Array;
|
|
310
|
+
signature?: Uint8Array;
|
|
311
|
+
output?: Uint8Array;
|
|
312
|
+
input?: Uint8Array;
|
|
313
|
+
network?: Network;
|
|
314
|
+
useHybrid?: boolean;
|
|
315
|
+
useUncompressed?: boolean;
|
|
316
|
+
}, opts?: PaymentOpts);
|
|
317
|
+
|
|
318
|
+
// Getters
|
|
319
|
+
get name(): 'p2pkh';
|
|
320
|
+
get network(): Network;
|
|
321
|
+
get address(): string | undefined;
|
|
322
|
+
get hash(): Bytes20 | undefined;
|
|
323
|
+
get pubkey(): PublicKey | undefined;
|
|
324
|
+
get signature(): Signature | undefined;
|
|
325
|
+
get output(): Script | undefined;
|
|
326
|
+
get input(): Script | undefined;
|
|
327
|
+
get witness(): Uint8Array[] | undefined;
|
|
328
|
+
|
|
329
|
+
// Static factory methods
|
|
330
|
+
static fromPubkey(pubkey: PublicKey, network?: Network): P2PKH;
|
|
331
|
+
static fromAddress(address: string, network?: Network): P2PKH;
|
|
332
|
+
static fromHash(hash: Bytes20, network?: Network): P2PKH;
|
|
333
|
+
static fromOutput(output: Uint8Array, network?: Network): P2PKH;
|
|
334
|
+
|
|
335
|
+
toPayment(): P2PKHPayment;
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Factory Function
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
function p2pkh(a: Omit<P2PKHPayment, 'name'>, opts?: PaymentOpts): P2PKHPayment;
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### P2PKHPayment Interface
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
interface P2PKHPayment extends BasePayment {
|
|
349
|
+
readonly name: 'p2pkh';
|
|
350
|
+
readonly hash?: Bytes20 | undefined;
|
|
351
|
+
readonly pubkey?: PublicKey | undefined;
|
|
352
|
+
readonly signature?: Signature | undefined;
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Examples
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
import { P2PKH, p2pkh } from '@btc-vision/bitcoin';
|
|
360
|
+
|
|
361
|
+
// Create from public key
|
|
362
|
+
const payment = P2PKH.fromPubkey(pubkey);
|
|
363
|
+
console.log(payment.address); // 1BvBMSEYstWetq...
|
|
364
|
+
console.log(payment.hash); // 20-byte hash
|
|
365
|
+
console.log(payment.output); // OP_DUP OP_HASH160 {hash} OP_EQUALVERIFY OP_CHECKSIG
|
|
366
|
+
|
|
367
|
+
// Create from address
|
|
368
|
+
const fromAddr = P2PKH.fromAddress('1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2');
|
|
369
|
+
console.log(fromAddr.hash); // 20-byte pubkey hash
|
|
370
|
+
|
|
371
|
+
// Create from 20-byte hash
|
|
372
|
+
const fromHash = P2PKH.fromHash(hash160);
|
|
373
|
+
console.log(fromHash.address);
|
|
374
|
+
|
|
375
|
+
// Legacy factory function
|
|
376
|
+
const legacy = p2pkh({ pubkey });
|
|
377
|
+
const fromAddrLegacy = p2pkh({ address: '1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2' });
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## P2SH (Pay-to-Script-Hash)
|
|
383
|
+
|
|
384
|
+
P2SH allows spending to be based on a hash of a script, with the actual script revealed only at spend time. This enables complex spending conditions while keeping addresses short. Addresses start with `3` on mainnet.
|
|
385
|
+
|
|
386
|
+
### Overview
|
|
387
|
+
|
|
388
|
+
| Property | Value |
|
|
389
|
+
|----------|-------|
|
|
390
|
+
| SegWit version | N/A (legacy, but can wrap SegWit) |
|
|
391
|
+
| Address format | Base58Check (`3...` mainnet, `2...` testnet) |
|
|
392
|
+
| Hash algorithm | HASH160(redeemScript) = 20 bytes |
|
|
393
|
+
| Script size | 23 bytes |
|
|
394
|
+
| BIP | 16 |
|
|
395
|
+
|
|
396
|
+
### Script Structure
|
|
397
|
+
|
|
398
|
+
```
|
|
399
|
+
Output: OP_HASH160 {hash160(redeemScript)} OP_EQUAL
|
|
400
|
+
Input: {redeemScriptSig...} {redeemScript}
|
|
401
|
+
Witness: [] (or forwarded from wrapped SegWit)
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Dynamic Name
|
|
405
|
+
|
|
406
|
+
The `name` getter returns a dynamic string based on the nested redeem type:
|
|
407
|
+
- `'p2sh'` when no redeem type is known
|
|
408
|
+
- `'p2sh-p2wpkh'` when wrapping P2WPKH
|
|
409
|
+
- `'p2sh-p2wsh'` when wrapping P2WSH
|
|
410
|
+
|
|
411
|
+
### Class: P2SH
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
class P2SH {
|
|
415
|
+
static readonly NAME = 'p2sh';
|
|
416
|
+
|
|
417
|
+
constructor(params: {
|
|
418
|
+
address?: string;
|
|
419
|
+
hash?: Uint8Array;
|
|
420
|
+
output?: Uint8Array;
|
|
421
|
+
input?: Uint8Array;
|
|
422
|
+
redeem?: ScriptRedeem;
|
|
423
|
+
witness?: Uint8Array[];
|
|
424
|
+
network?: Network;
|
|
425
|
+
}, opts?: PaymentOpts);
|
|
426
|
+
|
|
427
|
+
// Getters
|
|
428
|
+
get name(): string; // Dynamic: 'p2sh' or 'p2sh-{redeemName}'
|
|
429
|
+
get network(): Network;
|
|
430
|
+
get address(): string | undefined;
|
|
431
|
+
get hash(): Bytes20 | undefined;
|
|
432
|
+
get output(): Script | undefined;
|
|
433
|
+
get input(): Script | undefined;
|
|
434
|
+
get redeem(): ScriptRedeem | undefined;
|
|
435
|
+
get witness(): Uint8Array[] | undefined;
|
|
436
|
+
|
|
437
|
+
// Static factory methods
|
|
438
|
+
static fromRedeem(redeem: ScriptRedeem, network?: Network): P2SH;
|
|
439
|
+
static fromAddress(address: string, network?: Network): P2SH;
|
|
440
|
+
static fromHash(hash: Bytes20, network?: Network): P2SH;
|
|
441
|
+
static fromOutput(output: Uint8Array, network?: Network): P2SH;
|
|
442
|
+
|
|
443
|
+
toPayment(): P2SHPayment;
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Factory Function
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
function p2sh(a: Omit<P2SHPayment, 'name'>, opts?: PaymentOpts): P2SHPayment;
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### P2SHPayment Interface
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
interface P2SHPayment extends BasePayment {
|
|
457
|
+
readonly name: string; // Dynamic name
|
|
458
|
+
readonly hash?: Bytes20 | undefined;
|
|
459
|
+
readonly signatures?: Uint8Array[] | undefined;
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Examples
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
import { P2SH, P2MS, p2sh, p2ms } from '@btc-vision/bitcoin';
|
|
467
|
+
|
|
468
|
+
// Wrap a multisig in P2SH (class)
|
|
469
|
+
const multisig = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
|
|
470
|
+
const p2shPayment = P2SH.fromRedeem({ output: multisig.output });
|
|
471
|
+
console.log(p2shPayment.address); // 3... address
|
|
472
|
+
console.log(p2shPayment.hash); // 20-byte script hash
|
|
473
|
+
|
|
474
|
+
// Decode an existing P2SH output
|
|
475
|
+
const decoded = P2SH.fromOutput(scriptPubKey);
|
|
476
|
+
console.log(decoded.hash); // 20-byte script hash
|
|
477
|
+
|
|
478
|
+
// Create from address
|
|
479
|
+
const fromAddr = P2SH.fromAddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy');
|
|
480
|
+
|
|
481
|
+
// Legacy factory function
|
|
482
|
+
const msig = p2ms({ m: 2, pubkeys: [pk1, pk2, pk3] });
|
|
483
|
+
const legacy = p2sh({ redeem: msig });
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## P2MS (Pay-to-Multisig)
|
|
489
|
+
|
|
490
|
+
P2MS is a bare multisig script where M-of-N signatures are required to spend the output. The public keys are embedded directly in the output script. P2MS has no address format and is typically wrapped in P2SH or P2WSH.
|
|
491
|
+
|
|
492
|
+
### Overview
|
|
493
|
+
|
|
494
|
+
| Property | Value |
|
|
495
|
+
|----------|-------|
|
|
496
|
+
| SegWit version | N/A (legacy) |
|
|
497
|
+
| Address format | None |
|
|
498
|
+
| Max N | 16 |
|
|
499
|
+
| BIP | 11 |
|
|
500
|
+
|
|
501
|
+
### Script Structure
|
|
502
|
+
|
|
503
|
+
```
|
|
504
|
+
Output: OP_{m} {pubKey1} {pubKey2} ... {pubKeyN} OP_{n} OP_CHECKMULTISIG
|
|
505
|
+
Input: OP_0 {sig1} {sig2} ... {sigM}
|
|
506
|
+
Witness: [] (empty)
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Dynamic Name
|
|
510
|
+
|
|
511
|
+
The `name` getter returns a dynamic string including the M-of-N parameters:
|
|
512
|
+
- `'p2ms'` when M and N are unknown
|
|
513
|
+
- `'p2ms(2 of 3)'` when M=2, N=3
|
|
514
|
+
|
|
515
|
+
### Class: P2MS
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
class P2MS {
|
|
519
|
+
static readonly NAME = 'p2ms';
|
|
520
|
+
|
|
521
|
+
constructor(params: {
|
|
522
|
+
m?: number;
|
|
523
|
+
n?: number;
|
|
524
|
+
pubkeys?: Uint8Array[];
|
|
525
|
+
signatures?: Uint8Array[];
|
|
526
|
+
output?: Uint8Array;
|
|
527
|
+
input?: Uint8Array;
|
|
528
|
+
network?: Network;
|
|
529
|
+
}, opts?: PaymentOpts);
|
|
530
|
+
|
|
531
|
+
// Getters
|
|
532
|
+
get name(): string; // Dynamic: 'p2ms' or 'p2ms(M of N)'
|
|
533
|
+
get network(): Network;
|
|
534
|
+
get m(): number | undefined;
|
|
535
|
+
get n(): number | undefined;
|
|
536
|
+
get pubkeys(): PublicKey[] | undefined;
|
|
537
|
+
get signatures(): Signature[] | undefined;
|
|
538
|
+
get output(): Script | undefined;
|
|
539
|
+
get input(): Script | undefined;
|
|
540
|
+
get witness(): Uint8Array[] | undefined;
|
|
541
|
+
|
|
542
|
+
// Static factory methods
|
|
543
|
+
static fromPubkeys(m: number, pubkeys: PublicKey[], network?: Network): P2MS;
|
|
544
|
+
static fromOutput(output: Uint8Array, network?: Network): P2MS;
|
|
545
|
+
static fromSignatures(
|
|
546
|
+
signatures: Signature[],
|
|
547
|
+
m?: number,
|
|
548
|
+
pubkeys?: PublicKey[],
|
|
549
|
+
network?: Network,
|
|
550
|
+
): P2MS;
|
|
551
|
+
|
|
552
|
+
toPayment(): P2MSPayment;
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Factory Function
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
function p2ms(a: Omit<P2MSPayment, 'name'>, opts?: PaymentOpts): P2MSPayment;
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### P2MSPayment Interface
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
interface P2MSPayment extends BasePayment {
|
|
566
|
+
readonly name: string; // Dynamic name
|
|
567
|
+
readonly m?: number | undefined;
|
|
568
|
+
readonly n?: number | undefined;
|
|
569
|
+
readonly pubkeys?: PublicKey[] | undefined;
|
|
570
|
+
readonly signatures?: Signature[] | undefined;
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Examples
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
import { P2MS, p2ms } from '@btc-vision/bitcoin';
|
|
578
|
+
|
|
579
|
+
// Create a 2-of-3 multisig (class)
|
|
580
|
+
const payment = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
|
|
581
|
+
console.log(payment.output); // OP_2 {pk1} {pk2} {pk3} OP_3 OP_CHECKMULTISIG
|
|
582
|
+
console.log(payment.m); // 2
|
|
583
|
+
console.log(payment.n); // 3
|
|
584
|
+
console.log(payment.name); // 'p2ms(2 of 3)'
|
|
585
|
+
|
|
586
|
+
// Decode an existing output
|
|
587
|
+
const decoded = P2MS.fromOutput(scriptPubKey);
|
|
588
|
+
console.log(decoded.pubkeys); // array of public keys
|
|
589
|
+
console.log(decoded.m); // required signatures
|
|
590
|
+
console.log(decoded.n); // total keys
|
|
591
|
+
|
|
592
|
+
// Create from signatures for spending
|
|
593
|
+
const spender = P2MS.fromSignatures([sig1, sig2], 2, [pk1, pk2, pk3]);
|
|
594
|
+
console.log(spender.input); // OP_0 {sig1} {sig2}
|
|
595
|
+
|
|
596
|
+
// Legacy factory function
|
|
597
|
+
const legacy = p2ms({ m: 2, pubkeys: [pubkey1, pubkey2, pubkey3] });
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
---
|
|
601
|
+
|
|
602
|
+
## P2WPKH (Pay-to-Witness-Public-Key-Hash)
|
|
603
|
+
|
|
604
|
+
P2WPKH is the native SegWit version of P2PKH. The witness program is a 20-byte pubkey hash, and spending requires the signature and public key in the witness stack (not the scriptSig). Addresses use bech32 encoding with the `bc1q` prefix on mainnet.
|
|
605
|
+
|
|
606
|
+
### Overview
|
|
607
|
+
|
|
608
|
+
| Property | Value |
|
|
609
|
+
|----------|-------|
|
|
610
|
+
| SegWit version | 0 (`OP_0`) |
|
|
611
|
+
| Address format | bech32 (`bc1q...` mainnet, `tb1q...` testnet, `bcrt1q...` regtest) |
|
|
612
|
+
| Hash algorithm | RIPEMD160(SHA256(pubkey)) = 20 bytes |
|
|
613
|
+
| Script size | 22 bytes |
|
|
614
|
+
| BIP | 141, 143 |
|
|
615
|
+
| Key requirement | Compressed keys only (33 bytes) |
|
|
616
|
+
|
|
617
|
+
### Script Structure
|
|
618
|
+
|
|
619
|
+
```
|
|
620
|
+
Output: OP_0 {hash160(pubkey)}
|
|
621
|
+
Input: (empty)
|
|
622
|
+
Witness: [{signature}, {pubkey}]
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### Class: P2WPKH
|
|
626
|
+
|
|
627
|
+
```typescript
|
|
628
|
+
class P2WPKH {
|
|
629
|
+
static readonly NAME = 'p2wpkh';
|
|
630
|
+
|
|
631
|
+
constructor(params: {
|
|
632
|
+
address?: string;
|
|
633
|
+
hash?: Uint8Array;
|
|
634
|
+
pubkey?: Uint8Array;
|
|
635
|
+
signature?: Uint8Array;
|
|
636
|
+
output?: Uint8Array;
|
|
637
|
+
witness?: Uint8Array[];
|
|
638
|
+
network?: Network;
|
|
639
|
+
}, opts?: PaymentOpts);
|
|
640
|
+
|
|
641
|
+
// Getters
|
|
642
|
+
get name(): 'p2wpkh';
|
|
643
|
+
get network(): Network;
|
|
644
|
+
get address(): string | undefined;
|
|
645
|
+
get hash(): Bytes20 | undefined;
|
|
646
|
+
get pubkey(): PublicKey | undefined;
|
|
647
|
+
get signature(): Signature | undefined;
|
|
648
|
+
get output(): Script | undefined;
|
|
649
|
+
get input(): Script | undefined; // Always empty for native SegWit
|
|
650
|
+
get witness(): Uint8Array[] | undefined;
|
|
651
|
+
|
|
652
|
+
// Static factory methods
|
|
653
|
+
static fromPubkey(pubkey: PublicKey, network?: Network): P2WPKH;
|
|
654
|
+
static fromAddress(address: string, network?: Network): P2WPKH;
|
|
655
|
+
static fromHash(hash: Bytes20, network?: Network): P2WPKH;
|
|
656
|
+
static fromOutput(output: Uint8Array, network?: Network): P2WPKH;
|
|
657
|
+
|
|
658
|
+
toPayment(): P2WPKHPayment;
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Factory Function
|
|
663
|
+
|
|
664
|
+
```typescript
|
|
665
|
+
function p2wpkh(a: Omit<P2WPKHPayment, 'name'>, opts?: PaymentOpts): P2WPKHPayment;
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
### P2WPKHPayment Interface
|
|
669
|
+
|
|
670
|
+
```typescript
|
|
671
|
+
interface P2WPKHPayment extends BasePayment {
|
|
672
|
+
readonly name: 'p2wpkh';
|
|
673
|
+
readonly hash?: Bytes20 | undefined;
|
|
674
|
+
readonly pubkey?: PublicKey | undefined;
|
|
675
|
+
readonly signature?: Signature | undefined;
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### Examples
|
|
680
|
+
|
|
681
|
+
```typescript
|
|
682
|
+
import { P2WPKH, p2wpkh } from '@btc-vision/bitcoin';
|
|
683
|
+
|
|
684
|
+
// Create from public key (class)
|
|
685
|
+
const payment = P2WPKH.fromPubkey(pubkey);
|
|
686
|
+
console.log(payment.address); // bc1q...
|
|
687
|
+
console.log(payment.hash); // 20-byte witness program
|
|
688
|
+
console.log(payment.output); // OP_0 {20-byte hash}
|
|
689
|
+
|
|
690
|
+
// Create from bech32 address
|
|
691
|
+
const fromAddr = P2WPKH.fromAddress('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4');
|
|
692
|
+
console.log(fromAddr.hash); // 20-byte witness program
|
|
693
|
+
|
|
694
|
+
// Create from hash
|
|
695
|
+
const fromHash = P2WPKH.fromHash(hash160);
|
|
696
|
+
console.log(fromHash.address);
|
|
697
|
+
|
|
698
|
+
// Legacy factory function
|
|
699
|
+
const legacy = p2wpkh({ pubkey });
|
|
700
|
+
const fromAddrLegacy = p2wpkh({ address: 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4' });
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
---
|
|
704
|
+
|
|
705
|
+
## P2WSH (Pay-to-Witness-Script-Hash)
|
|
706
|
+
|
|
707
|
+
P2WSH is the native SegWit version of P2SH. The witness program is a 32-byte SHA256 hash of the redeem script, and spending requires the witness stack with the script inputs and the script itself. Addresses use bech32 encoding.
|
|
708
|
+
|
|
709
|
+
### Overview
|
|
710
|
+
|
|
711
|
+
| Property | Value |
|
|
712
|
+
|----------|-------|
|
|
713
|
+
| SegWit version | 0 (`OP_0`) |
|
|
714
|
+
| Address format | bech32 (`bc1q...` mainnet, `tb1q...` testnet, `bcrt1q...` regtest) |
|
|
715
|
+
| Hash algorithm | SHA256(redeemScript) = 32 bytes |
|
|
716
|
+
| Script size | 34 bytes |
|
|
717
|
+
| BIP | 141, 143 |
|
|
718
|
+
| Max script size | 3600 bytes |
|
|
719
|
+
| Max non-push ops | 201 |
|
|
720
|
+
|
|
721
|
+
### Script Structure
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
Output: OP_0 {sha256(redeemScript)}
|
|
725
|
+
Input: (empty)
|
|
726
|
+
Witness: [{scriptSig...}, {redeemScript}]
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### Dynamic Name
|
|
730
|
+
|
|
731
|
+
The `name` getter returns a dynamic string based on the nested redeem type:
|
|
732
|
+
- `'p2wsh'` when no redeem type is known
|
|
733
|
+
- `'p2wsh-p2pk'` when wrapping P2PK
|
|
734
|
+
|
|
735
|
+
### Class: P2WSH
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
class P2WSH {
|
|
739
|
+
static readonly NAME = 'p2wsh';
|
|
740
|
+
|
|
741
|
+
constructor(params: {
|
|
742
|
+
address?: string;
|
|
743
|
+
hash?: Uint8Array;
|
|
744
|
+
output?: Uint8Array;
|
|
745
|
+
redeem?: ScriptRedeem;
|
|
746
|
+
witness?: Uint8Array[];
|
|
747
|
+
network?: Network;
|
|
748
|
+
}, opts?: PaymentOpts);
|
|
749
|
+
|
|
750
|
+
// Getters
|
|
751
|
+
get name(): string; // Dynamic: 'p2wsh' or 'p2wsh-{redeemName}'
|
|
752
|
+
get network(): Network;
|
|
753
|
+
get address(): string | undefined;
|
|
754
|
+
get hash(): Bytes32 | undefined;
|
|
755
|
+
get output(): Script | undefined;
|
|
756
|
+
get input(): Script | undefined; // Always empty for native SegWit
|
|
757
|
+
get redeem(): ScriptRedeem | undefined;
|
|
758
|
+
get witness(): Uint8Array[] | undefined;
|
|
759
|
+
|
|
760
|
+
// Static factory methods
|
|
761
|
+
static fromRedeem(redeem: ScriptRedeem, network?: Network): P2WSH;
|
|
762
|
+
static fromAddress(address: string, network?: Network): P2WSH;
|
|
763
|
+
static fromHash(hash: Bytes32, network?: Network): P2WSH;
|
|
764
|
+
static fromOutput(output: Uint8Array, network?: Network): P2WSH;
|
|
765
|
+
|
|
766
|
+
toPayment(): P2WSHPayment;
|
|
767
|
+
}
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Factory Function
|
|
771
|
+
|
|
772
|
+
```typescript
|
|
773
|
+
function p2wsh(a: Omit<P2WSHPayment, 'name'>, opts?: PaymentOpts): P2WSHPayment;
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### P2WSHPayment Interface
|
|
777
|
+
|
|
778
|
+
```typescript
|
|
779
|
+
interface P2WSHPayment extends BasePayment {
|
|
780
|
+
readonly name: string; // Dynamic name
|
|
781
|
+
readonly hash?: Bytes32 | undefined;
|
|
782
|
+
readonly redeem?: ScriptRedeem | undefined;
|
|
783
|
+
}
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
### Examples
|
|
787
|
+
|
|
788
|
+
```typescript
|
|
789
|
+
import { P2WSH, P2MS, p2wsh, p2ms } from '@btc-vision/bitcoin';
|
|
790
|
+
|
|
791
|
+
// Wrap a multisig in P2WSH (class)
|
|
792
|
+
const multisig = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
|
|
793
|
+
const p2wshPayment = P2WSH.fromRedeem({ output: multisig.output });
|
|
794
|
+
console.log(p2wshPayment.address); // bc1q... (62-character bech32)
|
|
795
|
+
console.log(p2wshPayment.hash); // 32-byte SHA256 hash
|
|
796
|
+
|
|
797
|
+
// Decode an existing output
|
|
798
|
+
const decoded = P2WSH.fromOutput(scriptPubKey);
|
|
799
|
+
console.log(decoded.hash); // 32-byte witness program
|
|
800
|
+
|
|
801
|
+
// Create from address
|
|
802
|
+
const fromAddr = P2WSH.fromAddress('bc1q...');
|
|
803
|
+
|
|
804
|
+
// Legacy factory function
|
|
805
|
+
const msig = p2ms({ m: 2, pubkeys: [pk1, pk2, pk3] });
|
|
806
|
+
const legacy = p2wsh({ redeem: msig });
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
---
|
|
810
|
+
|
|
811
|
+
## P2TR (Pay-to-Taproot)
|
|
812
|
+
|
|
813
|
+
P2TR is the Taproot output type (BIP 341). It supports both key-path spending (single Schnorr signature) and script-path spending (Merkle tree of scripts). Addresses use bech32m encoding with the `bc1p` prefix on mainnet.
|
|
814
|
+
|
|
815
|
+
### Overview
|
|
816
|
+
|
|
817
|
+
| Property | Value |
|
|
818
|
+
|----------|-------|
|
|
819
|
+
| SegWit version | 1 (`OP_1`) |
|
|
820
|
+
| Address format | bech32m (`bc1p...` mainnet, `tb1p...` testnet, `bcrt1p...` regtest) |
|
|
821
|
+
| BIP | 341, 342 |
|
|
822
|
+
| Key type | x-only public keys (32 bytes) |
|
|
823
|
+
| Key-path spend | Yes |
|
|
824
|
+
| Script-path spend | Yes |
|
|
825
|
+
|
|
826
|
+
### Script Structure
|
|
827
|
+
|
|
828
|
+
```
|
|
829
|
+
Output: OP_1 {32-byte x-only tweaked pubkey}
|
|
830
|
+
|
|
831
|
+
Key-path witness: [{schnorr_signature}]
|
|
832
|
+
|
|
833
|
+
Script-path witness: [{script inputs...}, {script}, {control block}]
|
|
834
|
+
Control block: [{version | parity}, {32-byte internal pubkey}, {merkle path...}]
|
|
835
|
+
Size: 33 + 32*m bytes (0 <= m <= 128)
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
### Class: P2TR
|
|
839
|
+
|
|
840
|
+
```typescript
|
|
841
|
+
class P2TR {
|
|
842
|
+
static readonly NAME = 'p2tr';
|
|
843
|
+
|
|
844
|
+
constructor(params: {
|
|
845
|
+
address?: string;
|
|
846
|
+
pubkey?: Uint8Array;
|
|
847
|
+
internalPubkey?: Uint8Array;
|
|
848
|
+
hash?: Uint8Array;
|
|
849
|
+
scriptTree?: Taptree;
|
|
850
|
+
signature?: Uint8Array;
|
|
851
|
+
output?: Uint8Array;
|
|
852
|
+
witness?: Uint8Array[];
|
|
853
|
+
redeem?: ScriptRedeem;
|
|
854
|
+
redeemVersion?: number;
|
|
855
|
+
network?: Network;
|
|
856
|
+
}, opts?: PaymentOpts);
|
|
857
|
+
|
|
858
|
+
// Getters
|
|
859
|
+
get name(): 'p2tr';
|
|
860
|
+
get network(): Network;
|
|
861
|
+
get address(): string | undefined;
|
|
862
|
+
get pubkey(): XOnlyPublicKey | undefined; // Tweaked output pubkey
|
|
863
|
+
get internalPubkey(): XOnlyPublicKey | undefined; // Untweaked internal pubkey
|
|
864
|
+
get hash(): Bytes32 | undefined; // Merkle root
|
|
865
|
+
get signature(): SchnorrSignature | undefined;
|
|
866
|
+
get output(): Script | undefined;
|
|
867
|
+
get redeem(): ScriptRedeem | undefined;
|
|
868
|
+
get redeemVersion(): number; // Default: 0xc0
|
|
869
|
+
get witness(): Uint8Array[] | undefined;
|
|
870
|
+
|
|
871
|
+
// Static factory methods
|
|
872
|
+
static fromInternalPubkey(
|
|
873
|
+
internalPubkey: XOnlyPublicKey,
|
|
874
|
+
scriptTree?: Taptree,
|
|
875
|
+
network?: Network,
|
|
876
|
+
): P2TR;
|
|
877
|
+
static fromAddress(address: string, network?: Network): P2TR;
|
|
878
|
+
static fromOutput(output: Uint8Array, network?: Network): P2TR;
|
|
879
|
+
static fromSignature(
|
|
880
|
+
signature: SchnorrSignature,
|
|
881
|
+
internalPubkey?: XOnlyPublicKey,
|
|
882
|
+
network?: Network,
|
|
883
|
+
): P2TR;
|
|
884
|
+
|
|
885
|
+
toPayment(): P2TRPayment;
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
### Factory Function
|
|
890
|
+
|
|
891
|
+
```typescript
|
|
892
|
+
function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPayment;
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
### P2TRPayment Interface
|
|
896
|
+
|
|
897
|
+
```typescript
|
|
898
|
+
interface P2TRPayment extends BasePayment {
|
|
899
|
+
readonly name: 'p2tr';
|
|
900
|
+
readonly pubkey?: XOnlyPublicKey | undefined;
|
|
901
|
+
readonly internalPubkey?: XOnlyPublicKey | undefined;
|
|
902
|
+
readonly hash?: Bytes32 | undefined;
|
|
903
|
+
readonly scriptTree?: Taptree | undefined;
|
|
904
|
+
readonly signature?: SchnorrSignature | undefined;
|
|
905
|
+
readonly redeemVersion?: number | undefined;
|
|
906
|
+
readonly redeem?: ScriptRedeem | undefined;
|
|
907
|
+
}
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
### Examples
|
|
911
|
+
|
|
912
|
+
```typescript
|
|
913
|
+
import { P2TR, p2tr } from '@btc-vision/bitcoin';
|
|
914
|
+
import * as script from '@btc-vision/bitcoin/script';
|
|
915
|
+
|
|
916
|
+
// Key-path only (no scripts)
|
|
917
|
+
const keyOnly = P2TR.fromInternalPubkey(internalPubkey);
|
|
918
|
+
console.log(keyOnly.address); // bc1p...
|
|
919
|
+
console.log(keyOnly.pubkey); // 32-byte tweaked x-only pubkey
|
|
920
|
+
console.log(keyOnly.output); // OP_1 {32-byte pubkey}
|
|
921
|
+
|
|
922
|
+
// With script tree
|
|
923
|
+
const scriptTree = [
|
|
924
|
+
{ output: script1 },
|
|
925
|
+
{ output: script2 },
|
|
926
|
+
];
|
|
927
|
+
const withScripts = P2TR.fromInternalPubkey(internalPubkey, scriptTree);
|
|
928
|
+
console.log(withScripts.address);
|
|
929
|
+
|
|
930
|
+
// Script-path spending (with witness construction)
|
|
931
|
+
const spending = new P2TR({
|
|
932
|
+
internalPubkey,
|
|
933
|
+
scriptTree,
|
|
934
|
+
redeem: { output: script1 },
|
|
935
|
+
});
|
|
936
|
+
console.log(spending.witness);
|
|
937
|
+
// [script1, controlBlock]
|
|
938
|
+
// controlBlock = [version | parity, internalPubkey, ...merklePath]
|
|
939
|
+
|
|
940
|
+
// Decode from address
|
|
941
|
+
const fromAddr = P2TR.fromAddress('bc1p...');
|
|
942
|
+
console.log(fromAddr.pubkey); // 32-byte x-only pubkey
|
|
943
|
+
|
|
944
|
+
// Key-path spending with signature
|
|
945
|
+
const signed = P2TR.fromSignature(schnorrSignature, internalPubkey);
|
|
946
|
+
console.log(signed.witness); // [signature]
|
|
947
|
+
|
|
948
|
+
// Legacy factory function
|
|
949
|
+
const legacy = p2tr({ internalPubkey });
|
|
950
|
+
const withTree = p2tr({ internalPubkey, scriptTree });
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
---
|
|
954
|
+
|
|
955
|
+
## P2MR (Pay-to-Merkle-Root)
|
|
956
|
+
|
|
957
|
+
P2MR is a SegWit version 2 output type (BIP 360) that commits directly to the Merkle root of a script tree, removing the quantum-vulnerable key-path spend found in P2TR. There is no internal public key or key tweaking. Addresses use bech32m encoding with the `bc1z` prefix on mainnet.
|
|
958
|
+
|
|
959
|
+
### Overview
|
|
960
|
+
|
|
961
|
+
| Property | Value |
|
|
962
|
+
|----------|-------|
|
|
963
|
+
| SegWit version | 2 (`OP_2` = `0x52`) |
|
|
964
|
+
| Address format | bech32m (`bc1z...` mainnet, `tb1z...` testnet, `bcrt1z...` regtest) |
|
|
965
|
+
| BIP | 360 |
|
|
966
|
+
| Key-path spend | None (quantum-safe) |
|
|
967
|
+
| Script-path spend | Yes |
|
|
968
|
+
| Witness program | 32-byte Merkle root |
|
|
969
|
+
|
|
970
|
+
### Comparison with P2TR
|
|
971
|
+
|
|
972
|
+
| Aspect | P2TR (BIP 341) | P2MR (BIP 360) |
|
|
973
|
+
|--------|----------------|----------------|
|
|
974
|
+
| SegWit version | 1 (`OP_1`) | 2 (`OP_2`) |
|
|
975
|
+
| Address prefix | `bc1p` | `bc1z` |
|
|
976
|
+
| Key-path spend | Yes | No |
|
|
977
|
+
| Output commitment | `tweakKey(internalPubkey, merkleRoot)` | `merkleRoot` directly |
|
|
978
|
+
| Control block | `33 + 32*m` bytes (includes internal pubkey) | `1 + 32*m` bytes (no internal pubkey) |
|
|
979
|
+
| Control byte parity bit | 0 or 1 | Always 1 |
|
|
980
|
+
|
|
981
|
+
### Script Structure
|
|
982
|
+
|
|
983
|
+
```
|
|
984
|
+
Output: OP_2 {32-byte merkle root}
|
|
985
|
+
|
|
986
|
+
Script-path witness: [{script inputs...}, {script}, {control block}]
|
|
987
|
+
Control block: [{version_byte | 0x01}, {merkle_path...}]
|
|
988
|
+
Size: 1 + 32*m bytes (0 <= m <= 128)
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
### Class: P2MR
|
|
992
|
+
|
|
993
|
+
```typescript
|
|
994
|
+
class P2MR {
|
|
995
|
+
static readonly NAME = 'p2mr';
|
|
996
|
+
|
|
997
|
+
constructor(params: {
|
|
998
|
+
address?: string;
|
|
999
|
+
hash?: Uint8Array;
|
|
1000
|
+
scriptTree?: Taptree;
|
|
1001
|
+
output?: Uint8Array;
|
|
1002
|
+
witness?: Uint8Array[];
|
|
1003
|
+
redeem?: ScriptRedeem;
|
|
1004
|
+
redeemVersion?: number;
|
|
1005
|
+
network?: Network;
|
|
1006
|
+
}, opts?: PaymentOpts);
|
|
1007
|
+
|
|
1008
|
+
// Getters
|
|
1009
|
+
get name(): 'p2mr';
|
|
1010
|
+
get network(): Network;
|
|
1011
|
+
get address(): string | undefined;
|
|
1012
|
+
get hash(): Bytes32 | undefined; // Merkle root (= witness program)
|
|
1013
|
+
get output(): Script | undefined;
|
|
1014
|
+
get redeem(): ScriptRedeem | undefined;
|
|
1015
|
+
get redeemVersion(): number; // Default: 0xc0
|
|
1016
|
+
get witness(): Uint8Array[] | undefined;
|
|
1017
|
+
|
|
1018
|
+
// Static factory methods
|
|
1019
|
+
static fromScriptTree(scriptTree: Taptree, network?: Network): P2MR;
|
|
1020
|
+
static fromAddress(address: string, network?: Network): P2MR;
|
|
1021
|
+
static fromOutput(output: Uint8Array, network?: Network): P2MR;
|
|
1022
|
+
static fromHash(hash: Bytes32, network?: Network): P2MR;
|
|
1023
|
+
|
|
1024
|
+
toPayment(): P2MRPayment;
|
|
1025
|
+
}
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
### Factory Function
|
|
1029
|
+
|
|
1030
|
+
```typescript
|
|
1031
|
+
function p2mr(a: Omit<P2MRPayment, 'name'>, opts?: PaymentOpts): P2MRPayment;
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
### P2MRPayment Interface
|
|
1035
|
+
|
|
1036
|
+
```typescript
|
|
1037
|
+
interface P2MRPayment extends BasePayment {
|
|
1038
|
+
readonly name: 'p2mr';
|
|
1039
|
+
readonly hash?: Bytes32 | undefined;
|
|
1040
|
+
readonly scriptTree?: Taptree | undefined;
|
|
1041
|
+
readonly redeemVersion?: number | undefined;
|
|
1042
|
+
readonly redeem?: ScriptRedeem | undefined;
|
|
1043
|
+
}
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
### Examples
|
|
1047
|
+
|
|
1048
|
+
```typescript
|
|
1049
|
+
import { P2MR, p2mr } from '@btc-vision/bitcoin';
|
|
1050
|
+
import * as script from '@btc-vision/bitcoin/script';
|
|
1051
|
+
|
|
1052
|
+
// Create from a script tree
|
|
1053
|
+
const scriptTree = {
|
|
1054
|
+
output: script.compile([script.opcodes.OP_1]),
|
|
1055
|
+
};
|
|
1056
|
+
const payment = P2MR.fromScriptTree(scriptTree);
|
|
1057
|
+
console.log(payment.address); // bc1z...
|
|
1058
|
+
console.log(payment.hash); // 32-byte Merkle root
|
|
1059
|
+
console.log(payment.output); // OP_2 {32-byte hash}
|
|
1060
|
+
|
|
1061
|
+
// Multi-leaf tree
|
|
1062
|
+
const multiLeaf = [
|
|
1063
|
+
{ output: script1 },
|
|
1064
|
+
{ output: script2 },
|
|
1065
|
+
];
|
|
1066
|
+
const multi = P2MR.fromScriptTree(multiLeaf);
|
|
1067
|
+
|
|
1068
|
+
// Create from merkle root hash
|
|
1069
|
+
const fromHash = P2MR.fromHash(merkleRoot);
|
|
1070
|
+
console.log(fromHash.address); // bc1z...
|
|
1071
|
+
|
|
1072
|
+
// Create from address
|
|
1073
|
+
const fromAddr = P2MR.fromAddress('bc1z...');
|
|
1074
|
+
console.log(fromAddr.hash); // 32-byte Merkle root
|
|
1075
|
+
|
|
1076
|
+
// Script-path spending
|
|
1077
|
+
const spending = new P2MR({
|
|
1078
|
+
scriptTree: multiLeaf,
|
|
1079
|
+
redeem: { output: script1 },
|
|
1080
|
+
});
|
|
1081
|
+
console.log(spending.witness);
|
|
1082
|
+
// [script1, controlBlock]
|
|
1083
|
+
// controlBlock = [version | 0x01, ...merklePath]
|
|
1084
|
+
|
|
1085
|
+
// Legacy factory function
|
|
1086
|
+
const legacy = p2mr({ scriptTree });
|
|
1087
|
+
const legacyHash = p2mr({ hash: merkleRoot });
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
### P2MR Utilities
|
|
1091
|
+
|
|
1092
|
+
P2MR reuses the BIP 341 Merkle tree construction but with a simplified control block. Use `rootHashFromPathP2MR` instead of `rootHashFromPath` for P2MR:
|
|
1093
|
+
|
|
1094
|
+
```typescript
|
|
1095
|
+
import {
|
|
1096
|
+
rootHashFromPathP2MR,
|
|
1097
|
+
tapleafHash,
|
|
1098
|
+
toHashTree,
|
|
1099
|
+
findScriptPath,
|
|
1100
|
+
tapBranchHash,
|
|
1101
|
+
LEAF_VERSION_TAPSCRIPT,
|
|
1102
|
+
} from '@btc-vision/bitcoin';
|
|
1103
|
+
|
|
1104
|
+
// Compute leaf hash
|
|
1105
|
+
const leafHash = tapleafHash({
|
|
1106
|
+
output: redeemScript,
|
|
1107
|
+
version: LEAF_VERSION_TAPSCRIPT,
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
// Reconstruct merkle root from control block
|
|
1111
|
+
const merkleRoot = rootHashFromPathP2MR(controlBlock, leafHash);
|
|
1112
|
+
|
|
1113
|
+
// Build hash tree and find path
|
|
1114
|
+
const hashTree = toHashTree(scriptTree);
|
|
1115
|
+
const path = findScriptPath(hashTree, leafHash);
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
---
|
|
1119
|
+
|
|
1120
|
+
## P2OP (Pay-to-OPNet)
|
|
1121
|
+
|
|
1122
|
+
P2OP is a custom witness version 16 output type for the OPNet network. The witness program contains a deployment version byte followed by a hash160.
|
|
1123
|
+
|
|
1124
|
+
### Overview
|
|
1125
|
+
|
|
1126
|
+
| Property | Value |
|
|
1127
|
+
|----------|-------|
|
|
1128
|
+
| SegWit version | 16 (`OP_16`) |
|
|
1129
|
+
| Address format | bech32m (custom OPNet prefix from `network.bech32Opnet`) |
|
|
1130
|
+
| Witness program | 2-40 bytes (`{deploymentVersion:uint8}{hash160:20-bytes}`) |
|
|
1131
|
+
|
|
1132
|
+
### Script Structure
|
|
1133
|
+
|
|
1134
|
+
```
|
|
1135
|
+
Output: OP_16 {program}
|
|
1136
|
+
program = {deploymentVersion:uint8}{hash160:20-bytes|...}
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
### Class: P2OP
|
|
1140
|
+
|
|
1141
|
+
```typescript
|
|
1142
|
+
class P2OP {
|
|
1143
|
+
static readonly NAME = 'p2op';
|
|
1144
|
+
|
|
1145
|
+
constructor(params: {
|
|
1146
|
+
address?: string;
|
|
1147
|
+
program?: Uint8Array;
|
|
1148
|
+
deploymentVersion?: number;
|
|
1149
|
+
hash160?: Uint8Array;
|
|
1150
|
+
output?: Uint8Array;
|
|
1151
|
+
network?: Network;
|
|
1152
|
+
}, opts?: PaymentOpts);
|
|
1153
|
+
|
|
1154
|
+
// Getters
|
|
1155
|
+
get name(): 'p2op';
|
|
1156
|
+
get network(): Network;
|
|
1157
|
+
get address(): string | undefined;
|
|
1158
|
+
get program(): Uint8Array | undefined; // Full witness program (2-40 bytes)
|
|
1159
|
+
get deploymentVersion(): number | undefined; // First byte of program
|
|
1160
|
+
get hash160(): Bytes20 | undefined; // Remaining bytes of program
|
|
1161
|
+
get output(): Uint8Array | undefined;
|
|
1162
|
+
|
|
1163
|
+
// Static factory methods
|
|
1164
|
+
static fromProgram(program: Uint8Array, network?: Network): P2OP;
|
|
1165
|
+
static fromParts(deploymentVersion: number, hash160: Uint8Array, network?: Network): P2OP;
|
|
1166
|
+
static fromAddress(address: string, network?: Network): P2OP;
|
|
1167
|
+
static fromOutput(output: Uint8Array, network?: Network): P2OP;
|
|
1168
|
+
|
|
1169
|
+
toPayment(): P2OPPayment;
|
|
1170
|
+
}
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
### Factory Function
|
|
1174
|
+
|
|
1175
|
+
```typescript
|
|
1176
|
+
function p2op(a: {
|
|
1177
|
+
address?: string;
|
|
1178
|
+
program?: Uint8Array;
|
|
1179
|
+
deploymentVersion?: number;
|
|
1180
|
+
hash160?: Uint8Array;
|
|
1181
|
+
output?: Uint8Array;
|
|
1182
|
+
network?: Network;
|
|
1183
|
+
}, opts?: PaymentOpts): P2OPPayment;
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
### P2OPPayment Interface
|
|
1187
|
+
|
|
1188
|
+
```typescript
|
|
1189
|
+
interface P2OPPayment extends BasePayment {
|
|
1190
|
+
readonly name: 'p2op';
|
|
1191
|
+
readonly program?: Uint8Array | undefined;
|
|
1192
|
+
readonly deploymentVersion?: number | undefined;
|
|
1193
|
+
readonly hash160?: Bytes20 | undefined;
|
|
1194
|
+
}
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
### P2OPPaymentParams Interface
|
|
1198
|
+
|
|
1199
|
+
`P2OPPaymentParams` is the input type for the `p2op()` factory function. It is identical to `P2OPPayment` except that `name` is omitted and `deploymentVersion` defaults to `0` if not provided.
|
|
1200
|
+
|
|
1201
|
+
```typescript
|
|
1202
|
+
interface P2OPPaymentParams extends Omit<P2OPPayment, 'name' | 'deploymentVersion'> {
|
|
1203
|
+
readonly deploymentVersion?: number | undefined;
|
|
1204
|
+
}
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
### Examples
|
|
1208
|
+
|
|
1209
|
+
```typescript
|
|
1210
|
+
import { P2OP, p2op } from '@btc-vision/bitcoin';
|
|
1211
|
+
|
|
1212
|
+
// Create from witness program
|
|
1213
|
+
const payment = P2OP.fromProgram(programBytes);
|
|
1214
|
+
console.log(payment.address); // bech32m OPNet address
|
|
1215
|
+
console.log(payment.deploymentVersion); // first byte
|
|
1216
|
+
console.log(payment.hash160); // remaining bytes
|
|
1217
|
+
console.log(payment.output); // OP_16 {program}
|
|
1218
|
+
|
|
1219
|
+
// Create from deployment version and hash160
|
|
1220
|
+
const fromParts = P2OP.fromParts(0, hash160Bytes);
|
|
1221
|
+
console.log(fromParts.address);
|
|
1222
|
+
console.log(fromParts.program);
|
|
1223
|
+
|
|
1224
|
+
// Create from address
|
|
1225
|
+
const fromAddr = P2OP.fromAddress(opnetAddress);
|
|
1226
|
+
console.log(fromAddr.program);
|
|
1227
|
+
|
|
1228
|
+
// Decode from output script
|
|
1229
|
+
const decoded = P2OP.fromOutput(scriptPubKey);
|
|
1230
|
+
console.log(decoded.deploymentVersion);
|
|
1231
|
+
console.log(decoded.hash160);
|
|
1232
|
+
|
|
1233
|
+
// Legacy factory function
|
|
1234
|
+
const legacy = p2op({ program: programBytes });
|
|
1235
|
+
const legacyParts = p2op({ deploymentVersion: 0, hash160: hash160Bytes });
|
|
1236
|
+
```
|
|
1237
|
+
|
|
1238
|
+
---
|
|
1239
|
+
|
|
1240
|
+
## Embed (OP_RETURN Data)
|
|
1241
|
+
|
|
1242
|
+
Embed payments use OP_RETURN to store arbitrary data in the blockchain. These outputs are provably unspendable and are used for data storage, timestamping, and metadata.
|
|
1243
|
+
|
|
1244
|
+
### Overview
|
|
1245
|
+
|
|
1246
|
+
| Property | Value |
|
|
1247
|
+
|----------|-------|
|
|
1248
|
+
| SegWit version | N/A |
|
|
1249
|
+
| Address format | None |
|
|
1250
|
+
| Spendable | No (provably unspendable) |
|
|
1251
|
+
|
|
1252
|
+
### Script Structure
|
|
1253
|
+
|
|
1254
|
+
```
|
|
1255
|
+
Output: OP_RETURN {data1} {data2} ...
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
### Class: Embed
|
|
1259
|
+
|
|
1260
|
+
```typescript
|
|
1261
|
+
class Embed {
|
|
1262
|
+
static readonly NAME = 'embed';
|
|
1263
|
+
|
|
1264
|
+
constructor(params: {
|
|
1265
|
+
data?: Uint8Array[];
|
|
1266
|
+
output?: Uint8Array;
|
|
1267
|
+
network?: Network;
|
|
1268
|
+
}, opts?: PaymentOpts);
|
|
1269
|
+
|
|
1270
|
+
// Getters
|
|
1271
|
+
get name(): 'embed';
|
|
1272
|
+
get network(): Network;
|
|
1273
|
+
get data(): Uint8Array[];
|
|
1274
|
+
get output(): Script | undefined;
|
|
1275
|
+
|
|
1276
|
+
// Static factory methods
|
|
1277
|
+
static fromData(data: Uint8Array[], network?: Network): Embed;
|
|
1278
|
+
static fromOutput(output: Uint8Array, network?: Network): Embed;
|
|
1279
|
+
|
|
1280
|
+
toPayment(): EmbedPayment;
|
|
1281
|
+
}
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
### Factory Function
|
|
1285
|
+
|
|
1286
|
+
```typescript
|
|
1287
|
+
function p2data(a: Omit<EmbedPayment, 'name'>, opts?: PaymentOpts): EmbedPayment;
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
### EmbedPayment Interface
|
|
1291
|
+
|
|
1292
|
+
```typescript
|
|
1293
|
+
interface EmbedPayment extends BasePayment {
|
|
1294
|
+
readonly name: 'embed';
|
|
1295
|
+
readonly data: Uint8Array[];
|
|
1296
|
+
}
|
|
1297
|
+
```
|
|
1298
|
+
|
|
1299
|
+
### Examples
|
|
1300
|
+
|
|
1301
|
+
```typescript
|
|
1302
|
+
import { Embed, p2data } from '@btc-vision/bitcoin';
|
|
1303
|
+
|
|
1304
|
+
// Create from data chunks (class)
|
|
1305
|
+
const payment = Embed.fromData([
|
|
1306
|
+
new TextEncoder().encode('Hello'),
|
|
1307
|
+
new TextEncoder().encode('Bitcoin'),
|
|
1308
|
+
]);
|
|
1309
|
+
console.log(payment.output); // OP_RETURN {data1} {data2}
|
|
1310
|
+
console.log(payment.data); // [Uint8Array, Uint8Array]
|
|
1311
|
+
|
|
1312
|
+
// Decode from output script
|
|
1313
|
+
const decoded = Embed.fromOutput(scriptPubKey);
|
|
1314
|
+
console.log(decoded.data); // array of data chunks
|
|
1315
|
+
|
|
1316
|
+
// Legacy factory function
|
|
1317
|
+
const legacy = p2data({ data: [new TextEncoder().encode('Hello')] });
|
|
1318
|
+
const decodedLegacy = p2data({ output: scriptPubKey });
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
---
|
|
1322
|
+
|
|
1323
|
+
## Detecting Payment Types
|
|
1324
|
+
|
|
1325
|
+
The library provides factory-based detection functions for identifying script types from output scripts. These are located in `psbtutils` and work by attempting to parse the script with each payment factory, returning `true` on success and `false` on failure.
|
|
1326
|
+
|
|
1327
|
+
```typescript
|
|
1328
|
+
import {
|
|
1329
|
+
isP2PK,
|
|
1330
|
+
isP2PKH,
|
|
1331
|
+
isP2MS,
|
|
1332
|
+
isP2WPKH,
|
|
1333
|
+
isP2WSHScript,
|
|
1334
|
+
isP2SHScript,
|
|
1335
|
+
isP2TR,
|
|
1336
|
+
isP2MR,
|
|
1337
|
+
isP2OP,
|
|
1338
|
+
isP2A,
|
|
1339
|
+
} from '@btc-vision/bitcoin';
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
### Detection Functions
|
|
1343
|
+
|
|
1344
|
+
| Function | Detects | Script Pattern |
|
|
1345
|
+
|----------|---------|----------------|
|
|
1346
|
+
| `isP2PK(script)` | P2PK | `{pubkey} OP_CHECKSIG` |
|
|
1347
|
+
| `isP2PKH(script)` | P2PKH | `OP_DUP OP_HASH160 {20-byte} OP_EQUALVERIFY OP_CHECKSIG` |
|
|
1348
|
+
| `isP2MS(script)` | P2MS | `OP_m {pubkeys...} OP_n OP_CHECKMULTISIG` |
|
|
1349
|
+
| `isP2WPKH(script)` | P2WPKH | `OP_0 {20-byte}` |
|
|
1350
|
+
| `isP2WSHScript(script)` | P2WSH | `OP_0 {32-byte}` |
|
|
1351
|
+
| `isP2SHScript(script)` | P2SH | `OP_HASH160 {20-byte} OP_EQUAL` |
|
|
1352
|
+
| `isP2TR(script)` | P2TR | `OP_1 {32-byte}` |
|
|
1353
|
+
| `isP2MR(script)` | P2MR | `OP_2 {32-byte}` |
|
|
1354
|
+
| `isP2OP(script)` | P2OP | `OP_16 {2-40 bytes}` |
|
|
1355
|
+
| `isP2A(script)` | P2A (Anchor) | `OP_1 {0x4e73}` (exactly 4 bytes) |
|
|
1356
|
+
|
|
1357
|
+
### How Detection Works
|
|
1358
|
+
|
|
1359
|
+
Each detection function is created via `isPaymentFactory`, which wraps the corresponding legacy factory function in a try/catch:
|
|
1360
|
+
|
|
1361
|
+
```typescript
|
|
1362
|
+
function isPaymentFactory(payment: PaymentFunction): (script: Uint8Array) => boolean {
|
|
1363
|
+
return (script: Uint8Array): boolean => {
|
|
1364
|
+
try {
|
|
1365
|
+
payment({ output: script });
|
|
1366
|
+
return true;
|
|
1367
|
+
} catch {
|
|
1368
|
+
return false;
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
### Example Usage
|
|
1375
|
+
|
|
1376
|
+
```typescript
|
|
1377
|
+
import { isP2PKH, isP2TR, isP2MR, isP2WPKH } from '@btc-vision/bitcoin';
|
|
1378
|
+
|
|
1379
|
+
function classifyOutput(scriptPubKey: Uint8Array): string {
|
|
1380
|
+
if (isP2PKH(scriptPubKey)) return 'P2PKH';
|
|
1381
|
+
if (isP2WPKH(scriptPubKey)) return 'P2WPKH';
|
|
1382
|
+
if (isP2TR(scriptPubKey)) return 'P2TR';
|
|
1383
|
+
if (isP2MR(scriptPubKey)) return 'P2MR';
|
|
1384
|
+
return 'Unknown';
|
|
1385
|
+
}
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
---
|
|
1389
|
+
|
|
1390
|
+
## Class vs. Factory Function Pattern
|
|
1391
|
+
|
|
1392
|
+
Every payment type exposes two APIs:
|
|
1393
|
+
|
|
1394
|
+
### Class API (recommended for new code)
|
|
1395
|
+
|
|
1396
|
+
```typescript
|
|
1397
|
+
// Static factory methods return the class instance
|
|
1398
|
+
const payment = P2PKH.fromPubkey(pubkey);
|
|
1399
|
+
const address = payment.address; // lazy-computed getter
|
|
1400
|
+
```
|
|
1401
|
+
|
|
1402
|
+
### Legacy Factory Function
|
|
1403
|
+
|
|
1404
|
+
```typescript
|
|
1405
|
+
// Factory functions return a plain payment object
|
|
1406
|
+
const payment = p2pkh({ pubkey });
|
|
1407
|
+
const address = payment.address; // pre-computed property
|
|
1408
|
+
```
|
|
1409
|
+
|
|
1410
|
+
Both APIs accept the same parameters and produce equivalent results. The class API is preferred for new code because:
|
|
1411
|
+
|
|
1412
|
+
1. Static factory methods are more discoverable and type-safe.
|
|
1413
|
+
2. Getters are lazy-computed (only calculated when accessed).
|
|
1414
|
+
3. The class instance can be extended.
|
|
1415
|
+
|
|
1416
|
+
The `toPayment()` method on each class converts the instance to a plain payment object, which is what the factory functions return internally.
|
|
1417
|
+
|
|
1418
|
+
---
|
|
1419
|
+
|
|
1420
|
+
## Common Patterns
|
|
1421
|
+
|
|
1422
|
+
### Wrapping Scripts in P2SH
|
|
1423
|
+
|
|
1424
|
+
```typescript
|
|
1425
|
+
import { P2SH, P2MS, P2WPKH } from '@btc-vision/bitcoin';
|
|
1426
|
+
|
|
1427
|
+
// P2SH-P2MS (multisig in P2SH)
|
|
1428
|
+
const multisig = P2MS.fromPubkeys(2, [pk1, pk2, pk3]);
|
|
1429
|
+
const p2shMultisig = P2SH.fromRedeem({ output: multisig.output });
|
|
1430
|
+
|
|
1431
|
+
// P2SH-P2WPKH (wrapped SegWit)
|
|
1432
|
+
const segwit = P2WPKH.fromPubkey(pubkey);
|
|
1433
|
+
const p2shSegwit = P2SH.fromRedeem({ output: segwit.output });
|
|
1434
|
+
```
|
|
1435
|
+
|
|
1436
|
+
### Wrapping Scripts in P2WSH
|
|
1437
|
+
|
|
1438
|
+
```typescript
|
|
1439
|
+
import { P2WSH, P2MS } from '@btc-vision/bitcoin';
|
|
1440
|
+
|
|
1441
|
+
// P2WSH-P2MS (multisig in P2WSH)
|
|
1442
|
+
const multisig = P2MS.fromPubkeys(2, [pk1, pk2, pk3]);
|
|
1443
|
+
const p2wshMultisig = P2WSH.fromRedeem({ output: multisig.output });
|
|
1444
|
+
```
|
|
1445
|
+
|
|
1446
|
+
### Converting Between Representations
|
|
1447
|
+
|
|
1448
|
+
```typescript
|
|
1449
|
+
import { P2PKH } from '@btc-vision/bitcoin';
|
|
1450
|
+
|
|
1451
|
+
// Address -> Hash -> Output
|
|
1452
|
+
const fromAddr = P2PKH.fromAddress('1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2');
|
|
1453
|
+
const hash = fromAddr.hash;
|
|
1454
|
+
const output = fromAddr.output;
|
|
1455
|
+
|
|
1456
|
+
// Output -> Hash -> Address
|
|
1457
|
+
const fromOutput = P2PKH.fromOutput(scriptPubKey);
|
|
1458
|
+
const address = fromOutput.address;
|
|
1459
|
+
|
|
1460
|
+
// All getters are cross-derived lazily
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
### Disabling Validation
|
|
1464
|
+
|
|
1465
|
+
```typescript
|
|
1466
|
+
import { P2PKH } from '@btc-vision/bitcoin';
|
|
1467
|
+
|
|
1468
|
+
// Skip validation for performance
|
|
1469
|
+
const payment = new P2PKH(
|
|
1470
|
+
{ address: untrustedAddress },
|
|
1471
|
+
{ validate: false },
|
|
1472
|
+
);
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
### Allowing Incomplete Signatures
|
|
1476
|
+
|
|
1477
|
+
```typescript
|
|
1478
|
+
import { P2MS } from '@btc-vision/bitcoin';
|
|
1479
|
+
|
|
1480
|
+
// Allow OP_0 placeholders for missing signatures
|
|
1481
|
+
const payment = new P2MS(
|
|
1482
|
+
{ m: 2, pubkeys: [pk1, pk2, pk3], signatures: [sig1, placeholder] },
|
|
1483
|
+
{ allowIncomplete: true },
|
|
1484
|
+
);
|
|
1485
|
+
```
|