1 | 'use strict';
|
2 | Object.defineProperty(exports, '__esModule', { value: true });
|
3 | exports.toOutputScript =
|
4 | exports.fromOutputScript =
|
5 | exports.toBech32 =
|
6 | exports.toBase58Check =
|
7 | exports.fromBech32 =
|
8 | exports.fromBase58Check =
|
9 | void 0;
|
10 | const networks = require('./networks');
|
11 | const payments = require('./payments');
|
12 | const bscript = require('./script');
|
13 | const types_1 = require('./types');
|
14 | const bech32_1 = require('bech32');
|
15 | const bs58check = require('bs58check');
|
16 | const FUTURE_SEGWIT_MAX_SIZE = 40;
|
17 | const FUTURE_SEGWIT_MIN_SIZE = 2;
|
18 | const FUTURE_SEGWIT_MAX_VERSION = 16;
|
19 | const FUTURE_SEGWIT_MIN_VERSION = 2;
|
20 | const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
|
21 | const FUTURE_SEGWIT_VERSION_WARNING =
|
22 | 'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
|
23 | 'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
|
24 | 'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
|
25 | 'then decide when it is safe to use which version of segwit.';
|
26 | function _toFutureSegwitAddress(output, network) {
|
27 | const data = output.slice(2);
|
28 | if (
|
29 | data.length < FUTURE_SEGWIT_MIN_SIZE ||
|
30 | data.length > FUTURE_SEGWIT_MAX_SIZE
|
31 | )
|
32 | throw new TypeError('Invalid program length for segwit address');
|
33 | const version = output[0] - FUTURE_SEGWIT_VERSION_DIFF;
|
34 | if (
|
35 | version < FUTURE_SEGWIT_MIN_VERSION ||
|
36 | version > FUTURE_SEGWIT_MAX_VERSION
|
37 | )
|
38 | throw new TypeError('Invalid version for segwit address');
|
39 | if (output[1] !== data.length)
|
40 | throw new TypeError('Invalid script for segwit address');
|
41 | console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
42 | return toBech32(data, version, network.bech32);
|
43 | }
|
44 | function fromBase58Check(address) {
|
45 | const payload = Buffer.from(bs58check.decode(address));
|
46 |
|
47 | if (payload.length < 21) throw new TypeError(address + ' is too short');
|
48 | if (payload.length > 21) throw new TypeError(address + ' is too long');
|
49 | const version = payload.readUInt8(0);
|
50 | const hash = payload.slice(1);
|
51 | return { version, hash };
|
52 | }
|
53 | exports.fromBase58Check = fromBase58Check;
|
54 | function fromBech32(address) {
|
55 | let result;
|
56 | let version;
|
57 | try {
|
58 | result = bech32_1.bech32.decode(address);
|
59 | } catch (e) {}
|
60 | if (result) {
|
61 | version = result.words[0];
|
62 | if (version !== 0) throw new TypeError(address + ' uses wrong encoding');
|
63 | } else {
|
64 | result = bech32_1.bech32m.decode(address);
|
65 | version = result.words[0];
|
66 | if (version === 0) throw new TypeError(address + ' uses wrong encoding');
|
67 | }
|
68 | const data = bech32_1.bech32.fromWords(result.words.slice(1));
|
69 | return {
|
70 | version,
|
71 | prefix: result.prefix,
|
72 | data: Buffer.from(data),
|
73 | };
|
74 | }
|
75 | exports.fromBech32 = fromBech32;
|
76 | function toBase58Check(hash, version) {
|
77 | (0, types_1.typeforce)(
|
78 | (0, types_1.tuple)(types_1.Hash160bit, types_1.UInt8),
|
79 | arguments,
|
80 | );
|
81 | const payload = Buffer.allocUnsafe(21);
|
82 | payload.writeUInt8(version, 0);
|
83 | hash.copy(payload, 1);
|
84 | return bs58check.encode(payload);
|
85 | }
|
86 | exports.toBase58Check = toBase58Check;
|
87 | function toBech32(data, version, prefix) {
|
88 | const words = bech32_1.bech32.toWords(data);
|
89 | words.unshift(version);
|
90 | return version === 0
|
91 | ? bech32_1.bech32.encode(prefix, words)
|
92 | : bech32_1.bech32m.encode(prefix, words);
|
93 | }
|
94 | exports.toBech32 = toBech32;
|
95 | function fromOutputScript(output, network) {
|
96 |
|
97 | network = network || networks.bitcoin;
|
98 | try {
|
99 | return payments.p2pkh({ output, network }).address;
|
100 | } catch (e) {}
|
101 | try {
|
102 | return payments.p2sh({ output, network }).address;
|
103 | } catch (e) {}
|
104 | try {
|
105 | return payments.p2wpkh({ output, network }).address;
|
106 | } catch (e) {}
|
107 | try {
|
108 | return payments.p2wsh({ output, network }).address;
|
109 | } catch (e) {}
|
110 | try {
|
111 | return payments.p2tr({ output, network }).address;
|
112 | } catch (e) {}
|
113 | try {
|
114 | return _toFutureSegwitAddress(output, network);
|
115 | } catch (e) {}
|
116 | throw new Error(bscript.toASM(output) + ' has no matching Address');
|
117 | }
|
118 | exports.fromOutputScript = fromOutputScript;
|
119 | function toOutputScript(address, network) {
|
120 | network = network || networks.bitcoin;
|
121 | let decodeBase58;
|
122 | let decodeBech32;
|
123 | try {
|
124 | decodeBase58 = fromBase58Check(address);
|
125 | } catch (e) {}
|
126 | if (decodeBase58) {
|
127 | if (decodeBase58.version === network.pubKeyHash)
|
128 | return payments.p2pkh({ hash: decodeBase58.hash }).output;
|
129 | if (decodeBase58.version === network.scriptHash)
|
130 | return payments.p2sh({ hash: decodeBase58.hash }).output;
|
131 | } else {
|
132 | try {
|
133 | decodeBech32 = fromBech32(address);
|
134 | } catch (e) {}
|
135 | if (decodeBech32) {
|
136 | if (decodeBech32.prefix !== network.bech32)
|
137 | throw new Error(address + ' has an invalid prefix');
|
138 | if (decodeBech32.version === 0) {
|
139 | if (decodeBech32.data.length === 20)
|
140 | return payments.p2wpkh({ hash: decodeBech32.data }).output;
|
141 | if (decodeBech32.data.length === 32)
|
142 | return payments.p2wsh({ hash: decodeBech32.data }).output;
|
143 | } else if (decodeBech32.version === 1) {
|
144 | if (decodeBech32.data.length === 32)
|
145 | return payments.p2tr({ pubkey: decodeBech32.data }).output;
|
146 | } else if (
|
147 | decodeBech32.version >= FUTURE_SEGWIT_MIN_VERSION &&
|
148 | decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
|
149 | decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
|
150 | decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
|
151 | ) {
|
152 | console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
153 | return bscript.compile([
|
154 | decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
|
155 | decodeBech32.data,
|
156 | ]);
|
157 | }
|
158 | }
|
159 | }
|
160 | throw new Error(address + ' has no matching Script');
|
161 | }
|
162 | exports.toOutputScript = toOutputScript;
|