UNPKG

5.69 kBJavaScriptView Raw
1'use strict';
2Object.defineProperty(exports, '__esModule', { value: true });
3exports.toOutputScript =
4 exports.fromOutputScript =
5 exports.toBech32 =
6 exports.toBase58Check =
7 exports.fromBech32 =
8 exports.fromBase58Check =
9 void 0;
10const networks = require('./networks');
11const payments = require('./payments');
12const bscript = require('./script');
13const types_1 = require('./types');
14const bech32_1 = require('bech32');
15const bs58check = require('bs58check');
16const FUTURE_SEGWIT_MAX_SIZE = 40;
17const FUTURE_SEGWIT_MIN_SIZE = 2;
18const FUTURE_SEGWIT_MAX_VERSION = 16;
19const FUTURE_SEGWIT_MIN_VERSION = 2;
20const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
21const 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.';
26function _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}
44function fromBase58Check(address) {
45 const payload = Buffer.from(bs58check.decode(address));
46 // TODO: 4.0.0, move to "toOutputScript"
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}
53exports.fromBase58Check = fromBase58Check;
54function 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}
75exports.fromBech32 = fromBech32;
76function 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}
86exports.toBase58Check = toBase58Check;
87function 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}
94exports.toBech32 = toBech32;
95function fromOutputScript(output, network) {
96 // TODO: Network
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}
118exports.fromOutputScript = fromOutputScript;
119function 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}
162exports.toOutputScript = toOutputScript;