@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,820 @@
|
|
|
1
|
+
# Address Module
|
|
2
|
+
|
|
3
|
+
The address module provides encoding and decoding tools for all Bitcoin address formats, including Base58Check (legacy), Bech32/Bech32m (SegWit), and conversion between addresses and output scripts. It supports P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2MR, P2OP, and future SegWit versions.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
| Feature | Description |
|
|
8
|
+
|---------|-------------|
|
|
9
|
+
| Base58Check | Encode/decode legacy P2PKH and P2SH addresses |
|
|
10
|
+
| Bech32 | Encode/decode SegWit v0 addresses (P2WPKH, P2WSH) |
|
|
11
|
+
| Bech32m | Encode/decode SegWit v1+ addresses (P2TR, P2MR, P2OP, future) |
|
|
12
|
+
| Output scripts | Convert between addresses and their locking scripts |
|
|
13
|
+
| Networks | Bitcoin mainnet, testnet, regtest, Litecoin, Dogecoin, Dash, and more |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Supported Address Types
|
|
18
|
+
|
|
19
|
+
| Type | SegWit Version | Encoding | Mainnet Prefix | Testnet Prefix | Regtest Prefix | Script Pattern |
|
|
20
|
+
|------|---------------|----------|----------------|----------------|----------------|----------------|
|
|
21
|
+
| P2PKH | N/A | Base58Check | `1...` | `m...` / `n...` | `m...` / `n...` | `OP_DUP OP_HASH160 <20B> OP_EQUALVERIFY OP_CHECKSIG` |
|
|
22
|
+
| P2SH | N/A | Base58Check | `3...` | `2...` | `2...` | `OP_HASH160 <20B> OP_EQUAL` |
|
|
23
|
+
| P2WPKH | 0 | Bech32 | `bc1q...` | `tb1q...` | `bcrt1q...` | `OP_0 <20B>` |
|
|
24
|
+
| P2WSH | 0 | Bech32 | `bc1q...` | `tb1q...` | `bcrt1q...` | `OP_0 <32B>` |
|
|
25
|
+
| P2TR | 1 | Bech32m | `bc1p...` | `tb1p...` | `bcrt1p...` | `OP_1 <32B>` |
|
|
26
|
+
| P2MR | 2 | Bech32m | `bc1z...` | `tb1z...` | `bcrt1z...` | `OP_2 <32B>` |
|
|
27
|
+
| P2OP | 16 | Bech32m | `op1...` | `opt1...` | `opr1...` | `OP_16 <program>` |
|
|
28
|
+
| Future SegWit | 2-15 | Bech32m | `bc1...` | `tb1...` | `bcrt1...` | `OP_n <2-40B>` |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Network-Specific Prefixes
|
|
33
|
+
|
|
34
|
+
| Network | `bech32` | `bech32Opnet` | `pubKeyHash` | `scriptHash` |
|
|
35
|
+
|---------|----------|---------------|--------------|--------------|
|
|
36
|
+
| Bitcoin mainnet | `bc` | `op` | `0x00` | `0x05` |
|
|
37
|
+
| Bitcoin testnet | `tb` | `opt` | `0x6f` | `0xc4` |
|
|
38
|
+
| Bitcoin regtest | `bcrt` | `opr` | `0x6f` | `0xc4` |
|
|
39
|
+
| Litecoin mainnet | `ltc` | `opl` | `0x30` | `0x32` |
|
|
40
|
+
| Litecoin testnet | `tltc` | `oplt` | `0x6f` | `0x3a` |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import {
|
|
48
|
+
address,
|
|
49
|
+
networks,
|
|
50
|
+
} from '@btc-vision/bitcoin';
|
|
51
|
+
|
|
52
|
+
// Or import specific functions directly (re-exported from address module)
|
|
53
|
+
import {
|
|
54
|
+
fromBase58Check,
|
|
55
|
+
toBase58Check,
|
|
56
|
+
fromBech32,
|
|
57
|
+
toBech32,
|
|
58
|
+
fromOutputScript,
|
|
59
|
+
toOutputScript,
|
|
60
|
+
toFutureOPNetAddress,
|
|
61
|
+
_toFutureSegwitAddress,
|
|
62
|
+
isUnknownSegwitVersion,
|
|
63
|
+
FUTURE_SEGWIT_MAX_SIZE,
|
|
64
|
+
FUTURE_SEGWIT_MIN_SIZE,
|
|
65
|
+
FUTURE_SEGWIT_MAX_VERSION,
|
|
66
|
+
FUTURE_MAX_VERSION,
|
|
67
|
+
FUTURE_OPNET_VERSION,
|
|
68
|
+
FUTURE_SEGWIT_MIN_VERSION,
|
|
69
|
+
FUTURE_SEGWIT_VERSION_DIFF,
|
|
70
|
+
} from '@btc-vision/bitcoin';
|
|
71
|
+
|
|
72
|
+
// Types
|
|
73
|
+
import type {
|
|
74
|
+
Base58CheckResult,
|
|
75
|
+
Bech32Result,
|
|
76
|
+
ToOutputScriptOptions,
|
|
77
|
+
} from '@btc-vision/bitcoin';
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Interfaces
|
|
83
|
+
|
|
84
|
+
### Base58CheckResult
|
|
85
|
+
|
|
86
|
+
Returned by `fromBase58Check()` when decoding a legacy Base58Check address.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
interface Base58CheckResult {
|
|
90
|
+
/** The 20-byte address hash (HASH160 of public key or script) */
|
|
91
|
+
readonly hash: Bytes20;
|
|
92
|
+
/** The version byte: 0x00 for P2PKH, 0x05 for P2SH (mainnet) */
|
|
93
|
+
readonly version: number;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
| Field | Type | Description |
|
|
98
|
+
|-------|------|-------------|
|
|
99
|
+
| `hash` | `Bytes20` | 20-byte HASH160 payload |
|
|
100
|
+
| `version` | `number` | Version prefix byte identifying the address type and network |
|
|
101
|
+
|
|
102
|
+
### Bech32Result
|
|
103
|
+
|
|
104
|
+
Returned by `fromBech32()` when decoding a Bech32 or Bech32m address.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
interface Bech32Result {
|
|
108
|
+
/** Witness version: 0 for P2WPKH/P2WSH, 1 for P2TR, 2 for P2MR, 16 for P2OP */
|
|
109
|
+
version: number;
|
|
110
|
+
/** Human-readable prefix: "bc" for mainnet, "tb" for testnet, "bcrt" for regtest */
|
|
111
|
+
prefix: string;
|
|
112
|
+
/** Witness program: 20 bytes for P2WPKH, 32 bytes for P2WSH/P2TR/P2MR */
|
|
113
|
+
data: Uint8Array;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
| Field | Type | Description |
|
|
118
|
+
|-------|------|-------------|
|
|
119
|
+
| `version` | `number` | SegWit witness version (0-16) |
|
|
120
|
+
| `prefix` | `string` | Bech32 human-readable part (e.g., `"bc"`, `"tb"`, `"op"`) |
|
|
121
|
+
| `data` | `Uint8Array` | Decoded witness program bytes |
|
|
122
|
+
|
|
123
|
+
### ToOutputScriptOptions
|
|
124
|
+
|
|
125
|
+
Options object for `toOutputScript()`.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface ToOutputScriptOptions {
|
|
129
|
+
/** Network to use for encoding. Defaults to bitcoin mainnet. */
|
|
130
|
+
readonly network?: Network;
|
|
131
|
+
/**
|
|
132
|
+
* Optional callback for future segwit version warnings.
|
|
133
|
+
* Called with a warning string when encoding a future segwit version (v2-v15) address.
|
|
134
|
+
*/
|
|
135
|
+
readonly onFutureSegwitWarning?: (warning: string) => void;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Constants
|
|
142
|
+
|
|
143
|
+
| Constant | Value | Description |
|
|
144
|
+
|----------|-------|-------------|
|
|
145
|
+
| `FUTURE_SEGWIT_MAX_SIZE` | `40` | Maximum witness program length for future SegWit versions |
|
|
146
|
+
| `FUTURE_SEGWIT_MIN_SIZE` | `2` | Minimum witness program length for future SegWit versions |
|
|
147
|
+
| `FUTURE_SEGWIT_MAX_VERSION` | `15` | Maximum SegWit version for standard future addresses |
|
|
148
|
+
| `FUTURE_MAX_VERSION` | `16` | Maximum SegWit version (including OPNet) |
|
|
149
|
+
| `FUTURE_OPNET_VERSION` | `16` | SegWit version reserved for OPNet (P2OP) |
|
|
150
|
+
| `FUTURE_SEGWIT_MIN_VERSION` | `2` | Minimum SegWit version treated as "future" |
|
|
151
|
+
| `FUTURE_SEGWIT_VERSION_DIFF` | `0x50` | Offset between SegWit version number and the corresponding opcode (`OP_1` = `0x51`, so version 1 = `0x51 - 0x50`) |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## API Reference
|
|
156
|
+
|
|
157
|
+
### fromBase58Check()
|
|
158
|
+
|
|
159
|
+
Decodes a Base58Check-encoded address into its version byte and 20-byte hash.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
function fromBase58Check(address: string): Base58CheckResult
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| Parameter | Type | Description |
|
|
166
|
+
|-----------|------|-------------|
|
|
167
|
+
| `address` | `string` | A Base58Check-encoded address string |
|
|
168
|
+
|
|
169
|
+
**Returns:** `Base58CheckResult` with `version` and `hash` fields.
|
|
170
|
+
|
|
171
|
+
**Throws:** `TypeError` if the decoded payload is not exactly 21 bytes.
|
|
172
|
+
|
|
173
|
+
#### Example
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { address } from '@btc-vision/bitcoin';
|
|
177
|
+
|
|
178
|
+
// Decode a P2PKH mainnet address
|
|
179
|
+
const result = address.fromBase58Check('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH');
|
|
180
|
+
console.log(result.version); // 0 (P2PKH mainnet)
|
|
181
|
+
console.log(result.hash); // Uint8Array(20) - the HASH160
|
|
182
|
+
|
|
183
|
+
// Decode a P2SH mainnet address
|
|
184
|
+
const p2shResult = address.fromBase58Check('3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr');
|
|
185
|
+
console.log(p2shResult.version); // 5 (P2SH mainnet)
|
|
186
|
+
|
|
187
|
+
// Decode a testnet P2PKH address
|
|
188
|
+
const testnetResult = address.fromBase58Check('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r');
|
|
189
|
+
console.log(testnetResult.version); // 111 (0x6f, testnet P2PKH)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### toBase58Check()
|
|
195
|
+
|
|
196
|
+
Encodes a 20-byte hash and version byte into a Base58Check address string.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
function toBase58Check(hash: Bytes20, version: number): string
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
| Parameter | Type | Description |
|
|
203
|
+
|-----------|------|-------------|
|
|
204
|
+
| `hash` | `Bytes20` | 20-byte hash (HASH160 of public key or script) |
|
|
205
|
+
| `version` | `number` | Version byte (must be a valid UInt8, 0-255) |
|
|
206
|
+
|
|
207
|
+
**Returns:** Base58Check-encoded address string.
|
|
208
|
+
|
|
209
|
+
**Throws:** `TypeError` if `hash` is not exactly 20 bytes or `version` is not a valid UInt8.
|
|
210
|
+
|
|
211
|
+
#### Example
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { address, networks } from '@btc-vision/bitcoin';
|
|
215
|
+
import { fromHex } from '@btc-vision/bitcoin';
|
|
216
|
+
import type { Bytes20 } from '@btc-vision/bitcoin';
|
|
217
|
+
|
|
218
|
+
const hash = fromHex('751e76e8199196d454941c45d1b3a323f1433bd6') as Bytes20;
|
|
219
|
+
|
|
220
|
+
// Encode as P2PKH mainnet (version 0x00)
|
|
221
|
+
const p2pkhAddress = address.toBase58Check(hash, networks.bitcoin.pubKeyHash);
|
|
222
|
+
console.log(p2pkhAddress); // '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
|
|
223
|
+
|
|
224
|
+
// Encode as P2SH mainnet (version 0x05)
|
|
225
|
+
const p2shHash = fromHex('cd7b44d0b03f2d026d1e586d7ae18903b0d385f6') as Bytes20;
|
|
226
|
+
const p2shAddress = address.toBase58Check(p2shHash, networks.bitcoin.scriptHash);
|
|
227
|
+
console.log(p2shAddress); // '3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr'
|
|
228
|
+
|
|
229
|
+
// Encode as testnet P2PKH (version 0x6f)
|
|
230
|
+
const testnetAddress = address.toBase58Check(hash, networks.testnet.pubKeyHash);
|
|
231
|
+
console.log(testnetAddress); // 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r'
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### fromBech32()
|
|
237
|
+
|
|
238
|
+
Decodes a Bech32 or Bech32m address into its witness version, human-readable prefix, and witness program data. Automatically detects whether the address uses Bech32 (version 0) or Bech32m (version 1+).
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
function fromBech32(address: string): Bech32Result
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
| Parameter | Type | Description |
|
|
245
|
+
|-----------|------|-------------|
|
|
246
|
+
| `address` | `string` | A Bech32 or Bech32m encoded address |
|
|
247
|
+
|
|
248
|
+
**Returns:** `Bech32Result` with `version`, `prefix`, and `data` fields.
|
|
249
|
+
|
|
250
|
+
**Throws:** `TypeError` if the encoding is mismatched (e.g., Bech32 with version != 0, or Bech32m with version 0).
|
|
251
|
+
|
|
252
|
+
#### Example
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { address } from '@btc-vision/bitcoin';
|
|
256
|
+
|
|
257
|
+
// Decode a P2WPKH address (SegWit v0, Bech32)
|
|
258
|
+
const wpkh = address.fromBech32('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4');
|
|
259
|
+
console.log(wpkh.version); // 0
|
|
260
|
+
console.log(wpkh.prefix); // 'bc'
|
|
261
|
+
console.log(wpkh.data); // Uint8Array(20)
|
|
262
|
+
|
|
263
|
+
// Decode a P2WSH address (SegWit v0, Bech32)
|
|
264
|
+
const wsh = address.fromBech32(
|
|
265
|
+
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7'
|
|
266
|
+
);
|
|
267
|
+
console.log(wsh.version); // 0
|
|
268
|
+
console.log(wsh.prefix); // 'tb'
|
|
269
|
+
console.log(wsh.data); // Uint8Array(32)
|
|
270
|
+
|
|
271
|
+
// Decode a P2TR address (SegWit v1, Bech32m)
|
|
272
|
+
const tr = address.fromBech32(
|
|
273
|
+
'bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w'
|
|
274
|
+
);
|
|
275
|
+
console.log(tr.version); // 1
|
|
276
|
+
console.log(tr.prefix); // 'bc'
|
|
277
|
+
console.log(tr.data); // Uint8Array(32) - x-only public key
|
|
278
|
+
|
|
279
|
+
// Decode a P2MR address (SegWit v2, Bech32m, 32-byte program)
|
|
280
|
+
const mr = address.fromBech32('bc1z3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntssjqzpz');
|
|
281
|
+
console.log(mr.version); // 2
|
|
282
|
+
console.log(mr.prefix); // 'bc'
|
|
283
|
+
console.log(mr.data.length); // 32
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### toBech32()
|
|
289
|
+
|
|
290
|
+
Encodes witness program data into a Bech32 (version 0) or Bech32m (version 1+) address string. When the version is `FUTURE_OPNET_VERSION` (16) and an OPNet prefix is provided, the address is encoded with the OPNet prefix.
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
function toBech32(
|
|
294
|
+
data: Uint8Array,
|
|
295
|
+
version: number,
|
|
296
|
+
prefix: string,
|
|
297
|
+
prefixOpnet?: string,
|
|
298
|
+
): string
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
| Parameter | Type | Description |
|
|
302
|
+
|-----------|------|-------------|
|
|
303
|
+
| `data` | `Uint8Array` | Witness program bytes |
|
|
304
|
+
| `version` | `number` | SegWit witness version (0-16) |
|
|
305
|
+
| `prefix` | `string` | Bech32 human-readable prefix (e.g., `"bc"`, `"tb"`) |
|
|
306
|
+
| `prefixOpnet` | `string` (optional) | OPNet-specific prefix, used when version is 16 |
|
|
307
|
+
|
|
308
|
+
**Returns:** Encoded Bech32 or Bech32m address string.
|
|
309
|
+
|
|
310
|
+
#### Example
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
import { address, networks } from '@btc-vision/bitcoin';
|
|
314
|
+
import { fromHex } from '@btc-vision/bitcoin';
|
|
315
|
+
|
|
316
|
+
// Encode a P2WPKH address (version 0 uses Bech32)
|
|
317
|
+
const wpkhData = fromHex('751e76e8199196d454941c45d1b3a323f1433bd6');
|
|
318
|
+
const wpkhAddr = address.toBech32(wpkhData, 0, networks.bitcoin.bech32);
|
|
319
|
+
console.log(wpkhAddr); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
|
320
|
+
|
|
321
|
+
// Encode a P2TR address (version 1 uses Bech32m)
|
|
322
|
+
const trData = fromHex(
|
|
323
|
+
'8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
|
|
324
|
+
);
|
|
325
|
+
const trAddr = address.toBech32(trData, 1, networks.bitcoin.bech32);
|
|
326
|
+
console.log(trAddr); // 'bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w'
|
|
327
|
+
|
|
328
|
+
// Encode a P2MR address (version 2 uses Bech32m, 32-byte program required)
|
|
329
|
+
const mrData = fromHex(
|
|
330
|
+
'8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
|
|
331
|
+
);
|
|
332
|
+
const mrAddr = address.toBech32(mrData, 2, networks.bitcoin.bech32);
|
|
333
|
+
console.log(mrAddr); // 'bc1z3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntssjqzpz'
|
|
334
|
+
|
|
335
|
+
// Encode a testnet address
|
|
336
|
+
const testnetAddr = address.toBech32(wpkhData, 0, networks.testnet.bech32);
|
|
337
|
+
console.log(testnetAddr); // 'tb1q...'
|
|
338
|
+
|
|
339
|
+
// Encode a P2OP (OPNet) address (version 16 uses bech32Opnet prefix)
|
|
340
|
+
const opData = fromHex('751e');
|
|
341
|
+
const opAddr = address.toBech32(opData, 16, networks.bitcoin.bech32, networks.bitcoin.bech32Opnet);
|
|
342
|
+
console.log(opAddr); // 'op1sw50qcspuvz'
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
### fromOutputScript()
|
|
348
|
+
|
|
349
|
+
Converts an output script (`scriptPubKey`) into its corresponding address string. Uses fast byte-pattern matching for common script types (P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2MR) and falls back to payment constructors for exotic types like P2OP and future SegWit.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
function fromOutputScript(output: Uint8Array, network?: Network): string
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
| Parameter | Type | Description |
|
|
356
|
+
|-----------|------|-------------|
|
|
357
|
+
| `output` | `Uint8Array` | The output script (scriptPubKey) bytes |
|
|
358
|
+
| `network` | `Network` (optional) | Network configuration. Defaults to `networks.bitcoin`. |
|
|
359
|
+
|
|
360
|
+
**Returns:** The address string corresponding to the output script.
|
|
361
|
+
|
|
362
|
+
**Throws:** `Error` if the output script does not match any known address format.
|
|
363
|
+
|
|
364
|
+
#### Example
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { address, networks, script } from '@btc-vision/bitcoin';
|
|
368
|
+
|
|
369
|
+
// P2PKH output script to address
|
|
370
|
+
const p2pkhScript = script.fromASM(
|
|
371
|
+
'OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG'
|
|
372
|
+
);
|
|
373
|
+
const p2pkhAddr = address.fromOutputScript(p2pkhScript);
|
|
374
|
+
console.log(p2pkhAddr); // '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
|
|
375
|
+
|
|
376
|
+
// P2SH output script to address
|
|
377
|
+
const p2shScript = script.fromASM(
|
|
378
|
+
'OP_HASH160 cd7b44d0b03f2d026d1e586d7ae18903b0d385f6 OP_EQUAL'
|
|
379
|
+
);
|
|
380
|
+
const p2shAddr = address.fromOutputScript(p2shScript);
|
|
381
|
+
console.log(p2shAddr); // '3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr'
|
|
382
|
+
|
|
383
|
+
// P2WPKH output script to address
|
|
384
|
+
const p2wpkhScript = script.fromASM(
|
|
385
|
+
'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
|
|
386
|
+
);
|
|
387
|
+
const p2wpkhAddr = address.fromOutputScript(p2wpkhScript);
|
|
388
|
+
console.log(p2wpkhAddr); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
|
389
|
+
|
|
390
|
+
// P2TR output script to address
|
|
391
|
+
const p2trScript = script.fromASM(
|
|
392
|
+
'OP_1 8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
|
|
393
|
+
);
|
|
394
|
+
const p2trAddr = address.fromOutputScript(p2trScript);
|
|
395
|
+
console.log(p2trAddr); // 'bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w'
|
|
396
|
+
|
|
397
|
+
// P2MR output script to address (must be 34 bytes: OP_2 + 32-byte push)
|
|
398
|
+
const p2mrScript = script.fromASM(
|
|
399
|
+
'OP_2 8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
|
|
400
|
+
);
|
|
401
|
+
const p2mrAddr = address.fromOutputScript(p2mrScript);
|
|
402
|
+
console.log(p2mrAddr); // 'bc1z3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntssjqzpz'
|
|
403
|
+
|
|
404
|
+
// Using a specific network
|
|
405
|
+
const testnetScript = script.fromASM(
|
|
406
|
+
'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
|
|
407
|
+
);
|
|
408
|
+
const testnetAddr = address.fromOutputScript(testnetScript, networks.testnet);
|
|
409
|
+
console.log(testnetAddr); // 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
### toOutputScript()
|
|
415
|
+
|
|
416
|
+
Converts an address string into its corresponding output script (`scriptPubKey`). Accepts either a `Network` object or a `ToOutputScriptOptions` object as the second parameter.
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
function toOutputScript(
|
|
420
|
+
address: string,
|
|
421
|
+
networkOrOptions?: Network | ToOutputScriptOptions,
|
|
422
|
+
): Uint8Array
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
| Parameter | Type | Description |
|
|
426
|
+
|-----------|------|-------------|
|
|
427
|
+
| `address` | `string` | The address to convert |
|
|
428
|
+
| `networkOrOptions` | `Network \| ToOutputScriptOptions` (optional) | Network or options object. Defaults to `networks.bitcoin`. |
|
|
429
|
+
|
|
430
|
+
**Returns:** The output script as `Uint8Array`.
|
|
431
|
+
|
|
432
|
+
**Throws:** `TypeError` if the address does not match any known script pattern for the given network.
|
|
433
|
+
|
|
434
|
+
#### Example: Basic Usage
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
import { address, script, networks } from '@btc-vision/bitcoin';
|
|
438
|
+
|
|
439
|
+
// P2PKH address to output script
|
|
440
|
+
const p2pkhOutput = address.toOutputScript('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH');
|
|
441
|
+
console.log(script.toASM(p2pkhOutput));
|
|
442
|
+
// 'OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG'
|
|
443
|
+
|
|
444
|
+
// P2SH address to output script
|
|
445
|
+
const p2shOutput = address.toOutputScript('3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr');
|
|
446
|
+
console.log(script.toASM(p2shOutput));
|
|
447
|
+
// 'OP_HASH160 cd7b44d0b03f2d026d1e586d7ae18903b0d385f6 OP_EQUAL'
|
|
448
|
+
|
|
449
|
+
// P2WPKH address to output script
|
|
450
|
+
const wpkhOutput = address.toOutputScript(
|
|
451
|
+
'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
|
452
|
+
);
|
|
453
|
+
console.log(script.toASM(wpkhOutput));
|
|
454
|
+
// 'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
|
|
455
|
+
|
|
456
|
+
// P2TR address to output script
|
|
457
|
+
const trOutput = address.toOutputScript(
|
|
458
|
+
'bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0'
|
|
459
|
+
);
|
|
460
|
+
console.log(script.toASM(trOutput));
|
|
461
|
+
// 'OP_1 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
#### Example: With Network
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
import { address, script, networks } from '@btc-vision/bitcoin';
|
|
468
|
+
|
|
469
|
+
// Testnet P2PKH
|
|
470
|
+
const testnetOutput = address.toOutputScript(
|
|
471
|
+
'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r',
|
|
472
|
+
networks.testnet,
|
|
473
|
+
);
|
|
474
|
+
console.log(script.toASM(testnetOutput));
|
|
475
|
+
// 'OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG'
|
|
476
|
+
|
|
477
|
+
// Testnet P2SH
|
|
478
|
+
const testnetP2sh = address.toOutputScript(
|
|
479
|
+
'2NByiBUaEXrhmqAsg7BbLpcQSAQs1EDwt5w',
|
|
480
|
+
networks.testnet,
|
|
481
|
+
);
|
|
482
|
+
console.log(script.toASM(testnetP2sh));
|
|
483
|
+
// 'OP_HASH160 cd7b44d0b03f2d026d1e586d7ae18903b0d385f6 OP_EQUAL'
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
#### Example: With ToOutputScriptOptions
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
import { address, networks } from '@btc-vision/bitcoin';
|
|
490
|
+
|
|
491
|
+
// Use the options form to capture future segwit version warnings
|
|
492
|
+
const output = address.toOutputScript('bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs', {
|
|
493
|
+
network: networks.bitcoin,
|
|
494
|
+
onFutureSegwitWarning: (warning) => {
|
|
495
|
+
console.warn('Segwit warning:', warning);
|
|
496
|
+
// WARNING: Sending to a future segwit version address can lead to loss of funds...
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### Address Type Routing
|
|
502
|
+
|
|
503
|
+
`toOutputScript` automatically routes addresses to the correct payment constructor:
|
|
504
|
+
|
|
505
|
+
| Decoded Result | Condition | Payment Constructor |
|
|
506
|
+
|----------------|-----------|-------------------|
|
|
507
|
+
| Base58Check, version = `pubKeyHash` | Version matches network | `p2pkh()` |
|
|
508
|
+
| Base58Check, version = `scriptHash` | Version matches network | `p2sh()` |
|
|
509
|
+
| Bech32, version 0, 20-byte data | | `p2wpkh()` |
|
|
510
|
+
| Bech32, version 0, 32-byte data | | `p2wsh()` |
|
|
511
|
+
| Bech32m, version 1, 32-byte data | | `p2tr()` |
|
|
512
|
+
| Bech32m, version 2, 32-byte data | | `p2mr()` |
|
|
513
|
+
| Bech32m, version 16 | Network has `bech32Opnet` defined | `p2op()` |
|
|
514
|
+
| Bech32m, version 2-15, 2-40 byte data | Future SegWit | Raw `OP_n <data>` script |
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
### toFutureOPNetAddress()
|
|
519
|
+
|
|
520
|
+
Encodes an output script into a future OPNet address using Bech32m. This handles witness versions 15-16 with the OPNet-specific Bech32m prefix (`bech32Opnet`). The function parses the opcode and push-data from the raw output script to extract the witness version and program.
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
function toFutureOPNetAddress(output: Uint8Array, network: Network): string
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
| Parameter | Type | Description |
|
|
527
|
+
|-----------|------|-------------|
|
|
528
|
+
| `output` | `Uint8Array` | Output script buffer containing version opcode and witness program |
|
|
529
|
+
| `network` | `Network` | Network object (must have `bech32Opnet` defined) |
|
|
530
|
+
|
|
531
|
+
**Returns:** Bech32m-encoded OPNet address string.
|
|
532
|
+
|
|
533
|
+
**Throws:**
|
|
534
|
+
- `TypeError` if `output` is not a `Uint8Array`
|
|
535
|
+
- `Error` if the network does not support OPNet (`bech32Opnet` is falsy)
|
|
536
|
+
- `TypeError` if the program length is outside the valid range (2-40 bytes)
|
|
537
|
+
- `TypeError` if the witness version is outside the valid range (15-16)
|
|
538
|
+
|
|
539
|
+
#### Example
|
|
540
|
+
|
|
541
|
+
```typescript
|
|
542
|
+
import { address, networks, script } from '@btc-vision/bitcoin';
|
|
543
|
+
|
|
544
|
+
// Build a P2OP output script: OP_16 <program>
|
|
545
|
+
const opScript = script.fromASM('OP_16 751e');
|
|
546
|
+
const opAddress = address.toFutureOPNetAddress(opScript, networks.bitcoin);
|
|
547
|
+
console.log(opAddress); // 'op1sw50qcspuvz'
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
### _toFutureSegwitAddress()
|
|
553
|
+
|
|
554
|
+
Encodes an output script for future SegWit versions (v2-v15) into a Bech32m address. This is an internal helper used by `fromOutputScript()` as a fallback for non-standard future SegWit scripts. The function expects the output script to be in the format `[version_opcode, data_length, ...data]`.
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
function _toFutureSegwitAddress(output: Uint8Array, network: Network): string
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
| Parameter | Type | Description |
|
|
561
|
+
|-----------|------|-------------|
|
|
562
|
+
| `output` | `Uint8Array` | Output script with version opcode at byte 0, length at byte 1, then data |
|
|
563
|
+
| `network` | `Network` | Network object with `bech32` prefix |
|
|
564
|
+
|
|
565
|
+
**Returns:** Bech32m-encoded address string.
|
|
566
|
+
|
|
567
|
+
**Throws:**
|
|
568
|
+
- `TypeError` if the program length is outside 2-40 bytes
|
|
569
|
+
- `TypeError` if the version is outside 2-15
|
|
570
|
+
- `TypeError` if byte 1 does not match the actual data length
|
|
571
|
+
|
|
572
|
+
#### Example
|
|
573
|
+
|
|
574
|
+
```typescript
|
|
575
|
+
import { address, networks } from '@btc-vision/bitcoin';
|
|
576
|
+
|
|
577
|
+
// Build a raw future segwit output: OP_2 (0x52) + length + data
|
|
578
|
+
const output = new Uint8Array([
|
|
579
|
+
0x52, // OP_2
|
|
580
|
+
0x10, // 16 bytes of data
|
|
581
|
+
0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4,
|
|
582
|
+
0x54, 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23,
|
|
583
|
+
]);
|
|
584
|
+
const addr = address._toFutureSegwitAddress(output, networks.bitcoin);
|
|
585
|
+
console.log(addr); // 'bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs'
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
### isUnknownSegwitVersion()
|
|
591
|
+
|
|
592
|
+
Checks whether an output script corresponds to an unknown (future) SegWit version. Returns `true` if the script has a valid future SegWit structure (version 2-16, program length 2-40 bytes), excluding version 1 (Taproot, which is a known version).
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
const isUnknownSegwitVersion: (output: Uint8Array) => boolean
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
| Parameter | Type | Description |
|
|
599
|
+
|-----------|------|-------------|
|
|
600
|
+
| `output` | `Uint8Array` | The output script to check |
|
|
601
|
+
|
|
602
|
+
**Returns:** `true` if the script matches a future/unknown SegWit version pattern, `false` otherwise.
|
|
603
|
+
|
|
604
|
+
#### Example
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
import { address, script } from '@btc-vision/bitcoin';
|
|
608
|
+
|
|
609
|
+
// A SegWit v2 output is considered "unknown" (future)
|
|
610
|
+
const v2Script = new Uint8Array([
|
|
611
|
+
0x52, // OP_2
|
|
612
|
+
0x10, // 16 bytes
|
|
613
|
+
0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4,
|
|
614
|
+
0x54, 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23,
|
|
615
|
+
]);
|
|
616
|
+
console.log(address.isUnknownSegwitVersion(v2Script)); // true
|
|
617
|
+
|
|
618
|
+
// A SegWit v0 output (P2WPKH) is NOT unknown
|
|
619
|
+
const v0Script = new Uint8Array([
|
|
620
|
+
0x00, // OP_0
|
|
621
|
+
0x14, // 20 bytes
|
|
622
|
+
...new Uint8Array(20),
|
|
623
|
+
]);
|
|
624
|
+
console.log(address.isUnknownSegwitVersion(v0Script)); // false
|
|
625
|
+
|
|
626
|
+
// A SegWit v1 output (Taproot) is NOT unknown (it's recognized)
|
|
627
|
+
const v1Script = new Uint8Array([
|
|
628
|
+
0x51, // OP_1
|
|
629
|
+
0x20, // 32 bytes
|
|
630
|
+
...new Uint8Array(32),
|
|
631
|
+
]);
|
|
632
|
+
console.log(address.isUnknownSegwitVersion(v1Script)); // false
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
## Complete Workflow Examples
|
|
638
|
+
|
|
639
|
+
### Round-Trip: Address to Script and Back
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
import { address, script, networks } from '@btc-vision/bitcoin';
|
|
643
|
+
|
|
644
|
+
const originalAddress = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4';
|
|
645
|
+
|
|
646
|
+
// Address -> Output Script
|
|
647
|
+
const outputScript = address.toOutputScript(originalAddress);
|
|
648
|
+
console.log(script.toASM(outputScript));
|
|
649
|
+
// 'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
|
|
650
|
+
|
|
651
|
+
// Output Script -> Address
|
|
652
|
+
const recoveredAddress = address.fromOutputScript(outputScript);
|
|
653
|
+
console.log(recoveredAddress === originalAddress); // true
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### Detecting Address Type from a String
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
import { address } from '@btc-vision/bitcoin';
|
|
660
|
+
|
|
661
|
+
function getAddressType(addr: string): string {
|
|
662
|
+
// Try Base58Check first
|
|
663
|
+
try {
|
|
664
|
+
const decoded = address.fromBase58Check(addr);
|
|
665
|
+
if (decoded.version === 0x00) return 'P2PKH';
|
|
666
|
+
if (decoded.version === 0x05) return 'P2SH';
|
|
667
|
+
return `Base58Check (version ${decoded.version})`;
|
|
668
|
+
} catch {}
|
|
669
|
+
|
|
670
|
+
// Try Bech32/Bech32m
|
|
671
|
+
try {
|
|
672
|
+
const decoded = address.fromBech32(addr);
|
|
673
|
+
if (decoded.version === 0 && decoded.data.length === 20) return 'P2WPKH';
|
|
674
|
+
if (decoded.version === 0 && decoded.data.length === 32) return 'P2WSH';
|
|
675
|
+
if (decoded.version === 1 && decoded.data.length === 32) return 'P2TR';
|
|
676
|
+
if (decoded.version === 2 && decoded.data.length === 32) return 'P2MR';
|
|
677
|
+
if (decoded.version === 16) return 'P2OP';
|
|
678
|
+
return `Future SegWit v${decoded.version}`;
|
|
679
|
+
} catch {}
|
|
680
|
+
|
|
681
|
+
return 'Unknown';
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
console.log(getAddressType('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH')); // 'P2PKH'
|
|
685
|
+
console.log(getAddressType('3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr')); // 'P2SH'
|
|
686
|
+
console.log(getAddressType('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4')); // 'P2WPKH'
|
|
687
|
+
console.log(getAddressType('bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w')); // 'P2TR'
|
|
688
|
+
console.log(getAddressType('bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs')); // 'P2MR'
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### Multi-Network Address Generation
|
|
692
|
+
|
|
693
|
+
```typescript
|
|
694
|
+
import { address, networks } from '@btc-vision/bitcoin';
|
|
695
|
+
import type { Bytes20 } from '@btc-vision/bitcoin';
|
|
696
|
+
import { fromHex } from '@btc-vision/bitcoin';
|
|
697
|
+
|
|
698
|
+
const pubkeyHash = fromHex('751e76e8199196d454941c45d1b3a323f1433bd6') as Bytes20;
|
|
699
|
+
|
|
700
|
+
// Same hash, different networks produce different addresses
|
|
701
|
+
const mainnet = address.toBase58Check(pubkeyHash, networks.bitcoin.pubKeyHash);
|
|
702
|
+
const testnet = address.toBase58Check(pubkeyHash, networks.testnet.pubKeyHash);
|
|
703
|
+
const regtest = address.toBase58Check(pubkeyHash, networks.regtest.pubKeyHash);
|
|
704
|
+
|
|
705
|
+
console.log(mainnet); // '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
|
|
706
|
+
console.log(testnet); // 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r'
|
|
707
|
+
console.log(regtest); // 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r' (same version as testnet)
|
|
708
|
+
|
|
709
|
+
// SegWit addresses use the bech32 prefix
|
|
710
|
+
const mainnetBech32 = address.toBech32(pubkeyHash, 0, networks.bitcoin.bech32);
|
|
711
|
+
const testnetBech32 = address.toBech32(pubkeyHash, 0, networks.testnet.bech32);
|
|
712
|
+
const regtestBech32 = address.toBech32(pubkeyHash, 0, networks.regtest.bech32);
|
|
713
|
+
|
|
714
|
+
console.log(mainnetBech32); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
|
715
|
+
console.log(testnetBech32); // 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
|
|
716
|
+
console.log(regtestBech32); // 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7k0fey5p'
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Handling Future SegWit Version Warnings
|
|
720
|
+
|
|
721
|
+
```typescript
|
|
722
|
+
import { address, networks } from '@btc-vision/bitcoin';
|
|
723
|
+
|
|
724
|
+
// When decoding a future segwit address, you may want to warn users
|
|
725
|
+
const futureAddr = 'bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs';
|
|
726
|
+
|
|
727
|
+
const output = address.toOutputScript(futureAddr, {
|
|
728
|
+
network: networks.bitcoin,
|
|
729
|
+
onFutureSegwitWarning: (warning: string) => {
|
|
730
|
+
// Display this warning to the user before proceeding
|
|
731
|
+
console.warn(warning);
|
|
732
|
+
// "WARNING: Sending to a future segwit version address can lead to loss of funds..."
|
|
733
|
+
},
|
|
734
|
+
});
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
### Using with Payment Constructors
|
|
738
|
+
|
|
739
|
+
```typescript
|
|
740
|
+
import { payments, address, networks } from '@btc-vision/bitcoin';
|
|
741
|
+
|
|
742
|
+
// Generate address from a payment, then convert back to script
|
|
743
|
+
const payment = payments.p2wpkh({
|
|
744
|
+
hash: fromHex('751e76e8199196d454941c45d1b3a323f1433bd6') as Bytes20,
|
|
745
|
+
});
|
|
746
|
+
console.log(payment.address); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
|
747
|
+
|
|
748
|
+
// Convert the address back to the output script
|
|
749
|
+
const outputScript = address.toOutputScript(payment.address!);
|
|
750
|
+
// outputScript is identical to payment.output
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
---
|
|
754
|
+
|
|
755
|
+
## Error Handling
|
|
756
|
+
|
|
757
|
+
All address functions throw typed errors for invalid input:
|
|
758
|
+
|
|
759
|
+
```typescript
|
|
760
|
+
import { address } from '@btc-vision/bitcoin';
|
|
761
|
+
|
|
762
|
+
// Base58Check: too short
|
|
763
|
+
try {
|
|
764
|
+
address.fromBase58Check('7SeEnXWPaCCALbVrTnszCVGfRU8cGfx');
|
|
765
|
+
} catch (e) {
|
|
766
|
+
console.log(e.message); // '7SeEnXWPaCCALbVrTnszCVGfRU8cGfx is too short'
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// Base58Check: too long
|
|
770
|
+
try {
|
|
771
|
+
address.fromBase58Check('j9ywUkWg2fTQrouxxh5rSZhRvrjMkEUfuiKe');
|
|
772
|
+
} catch (e) {
|
|
773
|
+
console.log(e.message); // 'j9ywUkWg2fTQrouxxh5rSZhRvrjMkEUfuiKe is too long'
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// Bech32: wrong encoding (bech32 used with non-zero version)
|
|
777
|
+
try {
|
|
778
|
+
address.fromBech32('bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du');
|
|
779
|
+
} catch (e) {
|
|
780
|
+
console.log(e.message); // '... uses wrong encoding'
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// toOutputScript: no matching script
|
|
784
|
+
try {
|
|
785
|
+
address.toOutputScript('24kPZCmVgzfkpGdXExy56234MRHrsqQxNWE');
|
|
786
|
+
} catch (e) {
|
|
787
|
+
console.log(e.message); // '24kPZCmVgzfkpGdXExy56234MRHrsqQxNWE has no matching Script'
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// toOutputScript: invalid prefix for network
|
|
791
|
+
try {
|
|
792
|
+
address.toOutputScript('bc1sw50qgdz25j', { bech32: 'foo' } as any);
|
|
793
|
+
} catch (e) {
|
|
794
|
+
console.log(e.message); // 'bc1sw50qgdz25j has an invalid prefix'
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// fromOutputScript: unrecognized script
|
|
798
|
+
try {
|
|
799
|
+
address.fromOutputScript(new Uint8Array([0xff, 0x00]));
|
|
800
|
+
} catch (e) {
|
|
801
|
+
console.log(e.message); // '... has no matching Address'
|
|
802
|
+
}
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
---
|
|
806
|
+
|
|
807
|
+
## Script Pattern Detection (Internal)
|
|
808
|
+
|
|
809
|
+
`fromOutputScript()` uses fast byte-level matching for performance. Here are the exact patterns it checks, in order:
|
|
810
|
+
|
|
811
|
+
| Type | Length | Byte 0 | Byte 1 | Byte 2 | Tail Bytes |
|
|
812
|
+
|------|--------|--------|--------|--------|------------|
|
|
813
|
+
| P2PKH | 25 | `0x76` (OP_DUP) | `0xa9` (OP_HASH160) | `0x14` (push 20) | `[23]=0x88, [24]=0xac` |
|
|
814
|
+
| P2SH | 23 | `0xa9` (OP_HASH160) | `0x14` (push 20) | - | `[22]=0x87` |
|
|
815
|
+
| P2WPKH | 22 | `0x00` (OP_0) | `0x14` (push 20) | - | - |
|
|
816
|
+
| P2WSH | 34 | `0x00` (OP_0) | `0x20` (push 32) | - | - |
|
|
817
|
+
| P2TR | 34 | `0x51` (OP_1) | `0x20` (push 32) | - | - |
|
|
818
|
+
| P2MR | 34 | `0x52` (OP_2) | `0x20` (push 32) | - | - |
|
|
819
|
+
|
|
820
|
+
If none of these match, it falls back to `toFutureOPNetAddress()` and then `_toFutureSegwitAddress()`.
|