PageRenderTime 357ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/address.js

http://github.com/bitcoinjs/bitcoinjs-lib
JavaScript | 140 lines | 138 code | 0 blank | 2 comment | 25 complexity | c743c2587c16bd66e7b3723d0e0caec5 MD5 | raw file
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. exports.toOutputScript = exports.fromOutputScript = exports.toBech32 = exports.toBase58Check = exports.fromBech32 = exports.fromBase58Check = void 0;
  4. const networks = require('./networks');
  5. const payments = require('./payments');
  6. const bscript = require('./script');
  7. const types = require('./types');
  8. const bech32_1 = require('bech32');
  9. const bs58check = require('bs58check');
  10. const { typeforce } = types;
  11. const FUTURE_SEGWIT_MAX_SIZE = 40;
  12. const FUTURE_SEGWIT_MIN_SIZE = 2;
  13. const FUTURE_SEGWIT_MAX_VERSION = 16;
  14. const FUTURE_SEGWIT_MIN_VERSION = 1;
  15. const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
  16. function _toFutureSegwitAddress(output, network) {
  17. const data = output.slice(2);
  18. if (
  19. data.length < FUTURE_SEGWIT_MIN_SIZE ||
  20. data.length > FUTURE_SEGWIT_MAX_SIZE
  21. )
  22. throw new TypeError('Invalid program length for segwit address');
  23. const version = output[0] - FUTURE_SEGWIT_VERSION_DIFF;
  24. if (
  25. version < FUTURE_SEGWIT_MIN_VERSION ||
  26. version > FUTURE_SEGWIT_MAX_VERSION
  27. )
  28. throw new TypeError('Invalid version for segwit address');
  29. if (output[1] !== data.length)
  30. throw new TypeError('Invalid script for segwit address');
  31. return toBech32(data, version, network.bech32);
  32. }
  33. function fromBase58Check(address) {
  34. const payload = bs58check.decode(address);
  35. // TODO: 4.0.0, move to "toOutputScript"
  36. if (payload.length < 21) throw new TypeError(address + ' is too short');
  37. if (payload.length > 21) throw new TypeError(address + ' is too long');
  38. const version = payload.readUInt8(0);
  39. const hash = payload.slice(1);
  40. return { version, hash };
  41. }
  42. exports.fromBase58Check = fromBase58Check;
  43. function fromBech32(address) {
  44. let result;
  45. let version;
  46. try {
  47. result = bech32_1.bech32.decode(address);
  48. } catch (e) {}
  49. if (result) {
  50. version = result.words[0];
  51. if (version !== 0) throw new TypeError(address + ' uses wrong encoding');
  52. } else {
  53. result = bech32_1.bech32m.decode(address);
  54. version = result.words[0];
  55. if (version === 0) throw new TypeError(address + ' uses wrong encoding');
  56. }
  57. const data = bech32_1.bech32.fromWords(result.words.slice(1));
  58. return {
  59. version,
  60. prefix: result.prefix,
  61. data: Buffer.from(data),
  62. };
  63. }
  64. exports.fromBech32 = fromBech32;
  65. function toBase58Check(hash, version) {
  66. typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments);
  67. const payload = Buffer.allocUnsafe(21);
  68. payload.writeUInt8(version, 0);
  69. hash.copy(payload, 1);
  70. return bs58check.encode(payload);
  71. }
  72. exports.toBase58Check = toBase58Check;
  73. function toBech32(data, version, prefix) {
  74. const words = bech32_1.bech32.toWords(data);
  75. words.unshift(version);
  76. return version === 0
  77. ? bech32_1.bech32.encode(prefix, words)
  78. : bech32_1.bech32m.encode(prefix, words);
  79. }
  80. exports.toBech32 = toBech32;
  81. function fromOutputScript(output, network) {
  82. // TODO: Network
  83. network = network || networks.bitcoin;
  84. try {
  85. return payments.p2pkh({ output, network }).address;
  86. } catch (e) {}
  87. try {
  88. return payments.p2sh({ output, network }).address;
  89. } catch (e) {}
  90. try {
  91. return payments.p2wpkh({ output, network }).address;
  92. } catch (e) {}
  93. try {
  94. return payments.p2wsh({ output, network }).address;
  95. } catch (e) {}
  96. try {
  97. return _toFutureSegwitAddress(output, network);
  98. } catch (e) {}
  99. throw new Error(bscript.toASM(output) + ' has no matching Address');
  100. }
  101. exports.fromOutputScript = fromOutputScript;
  102. function toOutputScript(address, network) {
  103. network = network || networks.bitcoin;
  104. let decodeBase58;
  105. let decodeBech32;
  106. try {
  107. decodeBase58 = fromBase58Check(address);
  108. } catch (e) {}
  109. if (decodeBase58) {
  110. if (decodeBase58.version === network.pubKeyHash)
  111. return payments.p2pkh({ hash: decodeBase58.hash }).output;
  112. if (decodeBase58.version === network.scriptHash)
  113. return payments.p2sh({ hash: decodeBase58.hash }).output;
  114. } else {
  115. try {
  116. decodeBech32 = fromBech32(address);
  117. } catch (e) {}
  118. if (decodeBech32) {
  119. if (decodeBech32.prefix !== network.bech32)
  120. throw new Error(address + ' has an invalid prefix');
  121. if (decodeBech32.version === 0) {
  122. if (decodeBech32.data.length === 20)
  123. return payments.p2wpkh({ hash: decodeBech32.data }).output;
  124. if (decodeBech32.data.length === 32)
  125. return payments.p2wsh({ hash: decodeBech32.data }).output;
  126. } else if (
  127. decodeBech32.version >= FUTURE_SEGWIT_MIN_VERSION &&
  128. decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
  129. decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
  130. decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
  131. )
  132. return bscript.compile([
  133. decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
  134. decodeBech32.data,
  135. ]);
  136. }
  137. }
  138. throw new Error(address + ' has no matching Script');
  139. }
  140. exports.toOutputScript = toOutputScript;