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 | |
10 |
|
11 |
|
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 |
|
37 | var bs58check = require('bs58check')
|
38 | var cashaddr = require('cashaddrjs')
|
39 |
|
40 | /**
|
41 | * General purpose Bitcoin Cash address detection and translation.<br />
|
42 | * Supports all major Bitcoin Cash address formats.<br />
|
43 | * Currently:
|
44 | * <ul>
|
45 | * <li> Legacy format </li>
|
46 | * <li> Bitpay format </li>
|
47 | * <li> Cashaddr format </li>
|
48 | * </ul>
|
49 | * @module bchaddr
|
50 | */
|
51 |
|
52 | /**
|
53 | * @static
|
54 | * Supported Bitcoin Cash address formats.
|
55 | */
|
56 | var Format = {}
|
57 | Format.Legacy = 'legacy'
|
58 | Format.Bitpay = 'bitpay'
|
59 | Format.Cashaddr = 'cashaddr'
|
60 |
|
61 | /**
|
62 | * @static
|
63 | * Supported networks.
|
64 | */
|
65 | var Network = {}
|
66 | Network.Mainnet = 'mainnet'
|
67 | Network.Testnet = 'testnet'
|
68 |
|
69 | /**
|
70 | * @static
|
71 | * Supported address types.
|
72 | */
|
73 | var Type = {}
|
74 | Type.P2PKH = 'p2pkh'
|
75 | Type.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 | */
|
83 | function 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 | */
|
99 | function 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 | */
|
110 | function 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 | */
|
121 | function 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 | */
|
132 | function 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 | */
|
147 | function 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 | */
|
162 | function toCashAddress (address) {
|
163 | var decoded = decodeAddress(address)
|
164 | return encodeAsCashaddr(decoded)
|
165 | }
|
166 |
|
167 | /**
|
168 | * Version byte table for base58 formats.
|
169 | * @private
|
170 | */
|
171 | var VERSION_BYTE = {}
|
172 | VERSION_BYTE[Format.Legacy] = {}
|
173 | VERSION_BYTE[Format.Legacy][Network.Mainnet] = {}
|
174 | VERSION_BYTE[Format.Legacy][Network.Mainnet][Type.P2PKH] = 0
|
175 | VERSION_BYTE[Format.Legacy][Network.Mainnet][Type.P2SH] = 5
|
176 | VERSION_BYTE[Format.Legacy][Network.Testnet] = {}
|
177 | VERSION_BYTE[Format.Legacy][Network.Testnet][Type.P2PKH] = 111
|
178 | VERSION_BYTE[Format.Legacy][Network.Testnet][Type.P2SH] = 196
|
179 | VERSION_BYTE[Format.Bitpay] = {}
|
180 | VERSION_BYTE[Format.Bitpay][Network.Mainnet] = {}
|
181 | VERSION_BYTE[Format.Bitpay][Network.Mainnet][Type.P2PKH] = 28
|
182 | VERSION_BYTE[Format.Bitpay][Network.Mainnet][Type.P2SH] = 40
|
183 | VERSION_BYTE[Format.Bitpay][Network.Testnet] = {}
|
184 | VERSION_BYTE[Format.Bitpay][Network.Testnet][Type.P2PKH] = 111
|
185 | VERSION_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 | */
|
194 | function 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 | */
|
211 | var 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 | */
|
220 | function 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 | */
|
284 | function 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 < 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 | */
|
310 | function 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 | */
|
343 | function 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 | */
|
357 | function 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 | */
|
371 | function 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 | */
|
385 | function 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 | */
|
396 | function 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 | */
|
407 | function 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 | */
|
418 | function 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 | */
|
429 | function 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 | */
|
440 | function 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 | */
|
451 | function 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 | */
|
460 | function 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 |
|
467 | InvalidAddressError.prototype = Object.create(Error.prototype)
|
468 |
|
469 | module.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>
|