UNPKG

13.9 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <title>JSDoc: Source: bchaddr.js</title>
6
7 <script src="scripts/prettify/prettify.js"> </script>
8 <script src="scripts/prettify/lang-css.js"> </script>
9 <!--[if lt IE 9]>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 <![endif]-->
12 <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14</head>
15
16<body>
17
18<div id="main">
19
20 <h1 class="page-title">Source: bchaddr.js</h1>
21
22
23
24
25
26
27 <section>
28 <article>
29 <pre class="prettyprint source linenums"><code>/***
30 * @license
31 * https://github.com/bitcoincashjs/bchaddr
32 * Copyright (c) 2018-2019 Emilio Almansi
33 * Distributed under the MIT software license, see the accompanying
34 * file LICENSE or http://www.opensource.org/licenses/mit-license.php.
35 */
36
37var bs58check = require('bs58check')
38var cashaddr = require('cashaddrjs')
39
40/**
41 * General purpose Bitcoin Cash address detection and translation.&lt;br />
42 * Supports all major Bitcoin Cash address formats.&lt;br />
43 * Currently:
44 * &lt;ul>
45 * &lt;li> Legacy format &lt;/li>
46 * &lt;li> Bitpay format &lt;/li>
47 * &lt;li> Cashaddr format &lt;/li>
48 * &lt;/ul>
49 * @module bchaddr
50 */
51
52/**
53 * @static
54 * Supported Bitcoin Cash address formats.
55 */
56var Format = {}
57Format.Legacy = 'legacy'
58Format.Bitpay = 'bitpay'
59Format.Cashaddr = 'cashaddr'
60
61/**
62 * @static
63 * Supported networks.
64 */
65var Network = {}
66Network.Mainnet = 'mainnet'
67Network.Testnet = 'testnet'
68
69/**
70 * @static
71 * Supported address types.
72 */
73var Type = {}
74Type.P2PKH = 'p2pkh'
75Type.P2SH = 'p2sh'
76
77/**
78 * Returns a boolean indicating whether the given input is a valid Bitcoin Cash address.
79 * @static
80 * @param {*} input - Any input to check for validity.
81 * @returns {boolean}
82 */
83function isValidAddress (input) {
84 try {
85 decodeAddress(input)
86 return true
87 } catch (error) {
88 return false
89 }
90}
91
92/**
93 * Detects what is the given address' format.
94 * @static
95 * @param {string} address - A valid Bitcoin Cash address in any format.
96 * @return {string}
97 * @throws {InvalidAddressError}
98 */
99function detectAddressFormat (address) {
100 return decodeAddress(address).format
101}
102
103/**
104 * Detects what is the given address' network.
105 * @static
106 * @param {string} address - A valid Bitcoin Cash address in any format.
107 * @return {string}
108 * @throws {InvalidAddressError}
109 */
110function detectAddressNetwork (address) {
111 return decodeAddress(address).network
112}
113
114/**
115 * Detects what is the given address' type.
116 * @static
117 * @param {string} address - A valid Bitcoin Cash address in any format.
118 * @return {string}
119 * @throws {InvalidAddressError}
120 */
121function detectAddressType (address) {
122 return decodeAddress(address).type
123}
124
125/**
126 * Translates the given address into legacy format.
127 * @static
128 * @param {string} address - A valid Bitcoin Cash address in any format.
129 * @return {string}
130 * @throws {InvalidAddressError}
131 */
132function toLegacyAddress (address) {
133 var decoded = decodeAddress(address)
134 if (decoded.format === Format.Legacy) {
135 return address
136 }
137 return encodeAsLegacy(decoded)
138}
139
140/**
141 * Translates the given address into bitpay format.
142 * @static
143 * @param {string} address - A valid Bitcoin Cash address in any format.
144 * @return {string}
145 * @throws {InvalidAddressError}
146 */
147function toBitpayAddress (address) {
148 var decoded = decodeAddress(address)
149 if (decoded.format === Format.Bitpay) {
150 return address
151 }
152 return encodeAsBitpay(decoded)
153}
154
155/**
156 * Translates the given address into cashaddr format.
157 * @static
158 * @param {string} address - A valid Bitcoin Cash address in any format.
159 * @return {string}
160 * @throws {InvalidAddressError}
161 */
162function toCashAddress (address) {
163 var decoded = decodeAddress(address)
164 return encodeAsCashaddr(decoded)
165}
166
167/**
168 * Version byte table for base58 formats.
169 * @private
170 */
171var VERSION_BYTE = {}
172VERSION_BYTE[Format.Legacy] = {}
173VERSION_BYTE[Format.Legacy][Network.Mainnet] = {}
174VERSION_BYTE[Format.Legacy][Network.Mainnet][Type.P2PKH] = 0
175VERSION_BYTE[Format.Legacy][Network.Mainnet][Type.P2SH] = 5
176VERSION_BYTE[Format.Legacy][Network.Testnet] = {}
177VERSION_BYTE[Format.Legacy][Network.Testnet][Type.P2PKH] = 111
178VERSION_BYTE[Format.Legacy][Network.Testnet][Type.P2SH] = 196
179VERSION_BYTE[Format.Bitpay] = {}
180VERSION_BYTE[Format.Bitpay][Network.Mainnet] = {}
181VERSION_BYTE[Format.Bitpay][Network.Mainnet][Type.P2PKH] = 28
182VERSION_BYTE[Format.Bitpay][Network.Mainnet][Type.P2SH] = 40
183VERSION_BYTE[Format.Bitpay][Network.Testnet] = {}
184VERSION_BYTE[Format.Bitpay][Network.Testnet][Type.P2PKH] = 111
185VERSION_BYTE[Format.Bitpay][Network.Testnet][Type.P2SH] = 196
186
187/**
188 * Decodes the given address into its constituting hash, format, network and type.
189 * @private
190 * @param {string} address - A valid Bitcoin Cash address in any format.
191 * @return {object}
192 * @throws {InvalidAddressError}
193 */
194function decodeAddress (address) {
195 try {
196 return decodeBase58Address(address)
197 } catch (error) {
198 }
199 try {
200 return decodeCashAddress(address)
201 } catch (error) {
202 }
203 throw new InvalidAddressError()
204}
205
206/**
207 * Length of a valid base58check encoding payload: 1 byte for
208 * the version byte plus 20 bytes for a RIPEMD-160 hash.
209 * @private
210 */
211var BASE_58_CHECK_PAYLOAD_LENGTH = 21
212
213/**
214 * Attempts to decode the given address assuming it is a base58 address.
215 * @private
216 * @param {string} address - A valid Bitcoin Cash address in any format.
217 * @return {object}
218 * @throws {InvalidAddressError}
219 */
220function decodeBase58Address (address) {
221 try {
222 var payload = bs58check.decode(address)
223 if (payload.length !== BASE_58_CHECK_PAYLOAD_LENGTH) {
224 throw new InvalidAddressError()
225 }
226 var versionByte = payload[0]
227 var hash = Array.prototype.slice.call(payload, 1)
228 switch (versionByte) {
229 case VERSION_BYTE[Format.Legacy][Network.Mainnet][Type.P2PKH]:
230 return {
231 hash: hash,
232 format: Format.Legacy,
233 network: Network.Mainnet,
234 type: Type.P2PKH
235 }
236 case VERSION_BYTE[Format.Legacy][Network.Mainnet][Type.P2SH]:
237 return {
238 hash: hash,
239 format: Format.Legacy,
240 network: Network.Mainnet,
241 type: Type.P2SH
242 }
243 case VERSION_BYTE[Format.Legacy][Network.Testnet][Type.P2PKH]:
244 return {
245 hash: hash,
246 format: Format.Legacy,
247 network: Network.Testnet,
248 type: Type.P2PKH
249 }
250 case VERSION_BYTE[Format.Legacy][Network.Testnet][Type.P2SH]:
251 return {
252 hash: hash,
253 format: Format.Legacy,
254 network: Network.Testnet,
255 type: Type.P2SH
256 }
257 case VERSION_BYTE[Format.Bitpay][Network.Mainnet][Type.P2PKH]:
258 return {
259 hash: hash,
260 format: Format.Bitpay,
261 network: Network.Mainnet,
262 type: Type.P2PKH
263 }
264 case VERSION_BYTE[Format.Bitpay][Network.Mainnet][Type.P2SH]:
265 return {
266 hash: hash,
267 format: Format.Bitpay,
268 network: Network.Mainnet,
269 type: Type.P2SH
270 }
271 }
272 } catch (error) {
273 }
274 throw new InvalidAddressError()
275}
276
277/**
278 * Attempts to decode the given address assuming it is a cashaddr address.
279 * @private
280 * @param {string} address - A valid Bitcoin Cash address in any format.
281 * @return {object}
282 * @throws {InvalidAddressError}
283 */
284function decodeCashAddress (address) {
285 if (address.indexOf(':') !== -1) {
286 try {
287 return decodeCashAddressWithPrefix(address)
288 } catch (error) {
289 }
290 } else {
291 var prefixes = ['bitcoincash', 'bchtest', 'bchreg']
292 for (var i = 0; i &lt; prefixes.length; ++i) {
293 try {
294 var prefix = prefixes[i]
295 return decodeCashAddressWithPrefix(prefix + ':' + address)
296 } catch (error) {
297 }
298 }
299 }
300 throw new InvalidAddressError()
301}
302
303/**
304 * Attempts to decode the given address assuming it is a cashaddr address with explicit prefix.
305 * @private
306 * @param {string} address - A valid Bitcoin Cash address in any format.
307 * @return {object}
308 * @throws {InvalidAddressError}
309 */
310function decodeCashAddressWithPrefix (address) {
311 try {
312 var decoded = cashaddr.decode(address)
313 var hash = Array.prototype.slice.call(decoded.hash, 0)
314 var type = decoded.type === 'P2PKH' ? Type.P2PKH : Type.P2SH
315 switch (decoded.prefix) {
316 case 'bitcoincash':
317 return {
318 hash: hash,
319 format: Format.Cashaddr,
320 network: Network.Mainnet,
321 type: type
322 }
323 case 'bchtest':
324 case 'bchreg':
325 return {
326 hash: hash,
327 format: Format.Cashaddr,
328 network: Network.Testnet,
329 type: type
330 }
331 }
332 } catch (error) {
333 }
334 throw new InvalidAddressError()
335}
336
337/**
338 * Encodes the given decoded address into legacy format.
339 * @private
340 * @param {object} decoded
341 * @returns {string}
342 */
343function encodeAsLegacy (decoded) {
344 var versionByte = VERSION_BYTE[Format.Legacy][decoded.network][decoded.type]
345 var buffer = Buffer.alloc(1 + decoded.hash.length)
346 buffer[0] = versionByte
347 buffer.set(decoded.hash, 1)
348 return bs58check.encode(buffer)
349}
350
351/**
352 * Encodes the given decoded address into bitpay format.
353 * @private
354 * @param {object} decoded
355 * @returns {string}
356 */
357function encodeAsBitpay (decoded) {
358 var versionByte = VERSION_BYTE[Format.Bitpay][decoded.network][decoded.type]
359 var buffer = Buffer.alloc(1 + decoded.hash.length)
360 buffer[0] = versionByte
361 buffer.set(decoded.hash, 1)
362 return bs58check.encode(buffer)
363}
364
365/**
366 * Encodes the given decoded address into cashaddr format.
367 * @private
368 * @param {object} decoded
369 * @returns {string}
370 */
371function encodeAsCashaddr (decoded) {
372 var prefix = decoded.network === Network.Mainnet ? 'bitcoincash' : 'bchtest'
373 var type = decoded.type === Type.P2PKH ? 'P2PKH' : 'P2SH'
374 var hash = new Uint8Array(decoded.hash)
375 return cashaddr.encode(prefix, type, hash)
376}
377
378/**
379 * Returns a boolean indicating whether the address is in legacy format.
380 * @static
381 * @param {string} address - A valid Bitcoin Cash address in any format.
382 * @returns {boolean}
383 * @throws {InvalidAddressError}
384 */
385function isLegacyAddress (address) {
386 return detectAddressFormat(address) === Format.Legacy
387}
388
389/**
390 * Returns a boolean indicating whether the address is in bitpay format.
391 * @static
392 * @param {string} address - A valid Bitcoin Cash address in any format.
393 * @returns {boolean}
394 * @throws {InvalidAddressError}
395 */
396function isBitpayAddress (address) {
397 return detectAddressFormat(address) === Format.Bitpay
398}
399
400/**
401 * Returns a boolean indicating whether the address is in cashaddr format.
402 * @static
403 * @param {string} address - A valid Bitcoin Cash address in any format.
404 * @returns {boolean}
405 * @throws {InvalidAddressError}
406 */
407function isCashAddress (address) {
408 return detectAddressFormat(address) === Format.Cashaddr
409}
410
411/**
412 * Returns a boolean indicating whether the address is a mainnet address.
413 * @static
414 * @param {string} address - A valid Bitcoin Cash address in any format.
415 * @returns {boolean}
416 * @throws {InvalidAddressError}
417 */
418function isMainnetAddress (address) {
419 return detectAddressNetwork(address) === Network.Mainnet
420}
421
422/**
423 * Returns a boolean indicating whether the address is a testnet address.
424 * @static
425 * @param {string} address - A valid Bitcoin Cash address in any format.
426 * @returns {boolean}
427 * @throws {InvalidAddressError}
428 */
429function isTestnetAddress (address) {
430 return detectAddressNetwork(address) === Network.Testnet
431}
432
433/**
434 * Returns a boolean indicating whether the address is a p2pkh address.
435 * @static
436 * @param {string} address - A valid Bitcoin Cash address in any format.
437 * @returns {boolean}
438 * @throws {InvalidAddressError}
439 */
440function isP2PKHAddress (address) {
441 return detectAddressType(address) === Type.P2PKH
442}
443
444/**
445 * Returns a boolean indicating whether the address is a p2sh address.
446 * @static
447 * @param {string} address - A valid Bitcoin Cash address in any format.
448 * @returns {boolean}
449 * @throws {InvalidAddressError}
450 */
451function isP2SHAddress (address) {
452 return detectAddressType(address) === Type.P2SH
453}
454
455/**
456 * Error thrown when the address given as input is not a valid Bitcoin Cash address.
457 * @constructor
458 * InvalidAddressError
459 */
460function InvalidAddressError () {
461 var error = new Error()
462 this.name = error.name = 'InvalidAddressError'
463 this.message = error.message = 'Received an invalid Bitcoin Cash address as input.'
464 this.stack = error.stack
465}
466
467InvalidAddressError.prototype = Object.create(Error.prototype)
468
469module.exports = {
470 Format: Format,
471 Network: Network,
472 Type: Type,
473 isValidAddress: isValidAddress,
474 detectAddressFormat: detectAddressFormat,
475 detectAddressNetwork: detectAddressNetwork,
476 detectAddressType: detectAddressType,
477 toLegacyAddress: toLegacyAddress,
478 toBitpayAddress: toBitpayAddress,
479 toCashAddress: toCashAddress,
480 isLegacyAddress: isLegacyAddress,
481 isBitpayAddress: isBitpayAddress,
482 isCashAddress: isCashAddress,
483 isMainnetAddress: isMainnetAddress,
484 isTestnetAddress: isTestnetAddress,
485 isP2PKHAddress: isP2PKHAddress,
486 isP2SHAddress: isP2SHAddress,
487 InvalidAddressError: InvalidAddressError
488}
489</code></pre>
490 </article>
491 </section>
492
493
494
495
496</div>
497
498<nav>
499 <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-bchaddr.html">bchaddr</a></li></ul><h3>Classes</h3><ul><li><a href="module-bchaddr-InvalidAddressError.html">InvalidAddressError</a></li></ul>
500</nav>
501
502<br class="clear">
503
504<footer>
505 Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed May 29 2019 19:43:54 GMT-0300 (Argentina Standard Time)
506</footer>
507
508<script> prettyPrint(); </script>
509<script src="scripts/linenumber.js"> </script>
510</body>
511</html>