j-bitcoin
Version:
Comprehensive JavaScript cryptocurrency wallet library for Bitcoin (BTC), Bitcoin Cash (BCH), and Bitcoin SV (BSV) with custodial and non-custodial wallet support, threshold signatures, and multiple address formats
2,562 lines (1,048 loc) • 122 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Global</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Global</h1>
<section>
<header>
<h2></h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="CHARSET"><span class="type-signature">(constant) </span>CHARSET<span class="type-signature"> :string</span></h4>
<div class="description">
<p>Custom Base32 alphabet used in Bech32 and CashAddr address formats</p>
<p>This alphabet is carefully designed with several important properties:</p>
<ul>
<li><strong>No mixed case</strong>: All lowercase to avoid confusion</li>
<li><strong>No ambiguous characters</strong>: Excludes 1, b, i, o which can be confused</li>
<li><strong>Error detection</strong>: Character positioning aids in polynomial checksum validation</li>
<li><strong>Human readable</strong>: Avoids characters that look similar in common fonts</li>
</ul>
<p>The alphabet consists of: qpzry9x8gf2tvdw0s3jn54khce6mua7l</p>
<p><strong>Character Index Mapping:</strong></p>
<pre class="prettyprint source"><code>q=0, p=1, z=2, r=3, y=4, 9=5, x=6, 8=7, g=8, f=9, 2=10, t=11, v=12, d=13, w=14, 0=15,
s=16, 3=17, j=18, n=19, 5=20, 4=21, k=22, h=23, c=24, e=25, 6=26, m=27, u=28, a=29, 7=30, l=31
</code></pre>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">string</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_Base32.js.html">src/utilities/Base32.js</a>, <a href="src_utilities_Base32.js.html#line35">line 35</a>
</li></ul></dd>
</dl>
<h4 class="name" id="FEATURES"><span class="type-signature">(constant) </span>FEATURES<span class="type-signature"> :boolean</span></h4>
<div class="description">
<p>Library feature support matrix</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">boolean</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line284">line 284</a>
</li></ul></dd>
</dl>
<h4 class="name" id="NETWORKS"><span class="type-signature">(constant) </span>NETWORKS<span class="type-signature"> :Object</span></h4>
<div class="description">
<p>Supported cryptocurrency networks</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line314">line 314</a>
</li></ul></dd>
</dl>
<h4 class="name" id="table"><span class="type-signature">(constant) </span>table<span class="type-signature"> :string</span></h4>
<div class="description">
<p>Base58 alphabet used by Bitcoin (excludes confusing characters 0, O, I, l)</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">string</span>
</li>
</ul>
<dl class="details">
<dt class="tag-default">Default Value:</dt>
<dd class="tag-default"><ul class="dummy">
<li>123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz</li>
</ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_base58.js.html">src/utilities/base58.js</a>, <a href="src_utilities_base58.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="address"><span class="type-signature"></span>address<span class="signature">(versionByte, pubKey)</span><span class="type-signature"> → {string}</span></h4>
<div class="description">
<p>Generates a Bitcoin address from a public key using HASH160 and Base58Check encoding</p>
<p>This function implements the standard Bitcoin address generation algorithm:</p>
<p><strong>Address Generation Process:</strong></p>
<ol>
<li><strong>Double Hash</strong>: SHA256(public_key) → RIPEMD160(hash) = HASH160</li>
<li><strong>Version Prefix</strong>: Prepend network version byte (0x00 mainnet, 0x6f testnet)</li>
<li><strong>Checksum</strong>: Calculate SHA256(SHA256(version + hash160))[0:4]</li>
<li><strong>Encoding</strong>: Base58Check encode (version + hash160 + checksum)</li>
</ol>
<p><strong>Address Types by Version Byte:</strong></p>
<ul>
<li>0x00 (mainnet): Addresses starting with "1"</li>
<li>0x6f (testnet): Addresses starting with "m" or "n"</li>
<li>0x05 (mainnet P2SH): Addresses starting with "3" (not implemented here)</li>
</ul>
<p>The resulting address is a human-readable string that can receive Bitcoin payments
and corresponds directly to the provided public key.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>versionByte</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last"><p>Extended key version byte (determines address network)</p></td>
</tr>
<tr>
<td class="name"><code>pubKey</code></td>
<td class="type">
<span class="param-type">Buffer</span>
</td>
<td class="description last"><p>Compressed 33-byte public key</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_encodeKeys.js.html">src/utilities/encodeKeys.js</a>, <a href="src_utilities_encodeKeys.js.html#line345">line 345</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If public key is invalid format or length</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If version byte is not recognized</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
</ul>
<h5>Returns:</h5>
<div class="param-desc">
<p>Base58Check-encoded Bitcoin address</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Generate mainnet address
const pubKey = Buffer.from('0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2', 'hex');
const mainnetVersionByte = 0x0488b21e; // Extended public key version
const address = address(mainnetVersionByte, pubKey);
console.log(address);
// "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma" (mainnet address starting with "1")</code></pre>
<pre class="prettyprint"><code>// Generate testnet address
const testnetVersionByte = 0x043587cf; // Extended public key version (testnet)
const testAddress = address(testnetVersionByte, pubKey);
console.log(testAddress);
// "mhiH7BQkmD7LoosHhAAH5nE9YKGUcPz4hV" (testnet address starting with "m")</code></pre>
<pre class="prettyprint"><code>// Full workflow: private key → public key → address
import { getPublicKey } from '@noble/secp256k1';
const privateKey = Buffer.from('e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35', 'hex');
const publicKey = Buffer.from(getPublicKey(privateKey, true)); // Compressed
const bitcoinAddress = address(0x0488b21e, publicKey);
console.log('Private key:', privateKey.toString('hex'));
console.log('Public key:', publicKey.toString('hex'));
console.log('Address:', bitcoinAddress);</code></pre>
<pre class="prettyprint"><code>// Validate address generation
const knownPubKey = Buffer.from('0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 'hex');
const knownAddress = address(0x0488b21e, knownPubKey);
console.log(knownAddress);
// Should produce: "1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH"</code></pre>
<h4 class="name" id="b58encode"><span class="type-signature"></span>b58encode<span class="signature">(bufferKey)</span><span class="type-signature"> → {string}</span></h4>
<div class="description">
<p>Encodes binary data using Base58Check format with double SHA256 checksum</p>
<p>Base58Check encoding is Bitcoin's standard format for human-readable data
that needs integrity protection. The process involves:</p>
<p><strong>Encoding Algorithm:</strong></p>
<ol>
<li><strong>Input</strong>: Raw binary data (private keys, addresses, extended keys)</li>
<li><strong>Checksum</strong>: Calculate SHA256(SHA256(data)) and take first 4 bytes</li>
<li><strong>Concatenation</strong>: Append checksum to original data</li>
<li><strong>Base58 Encoding</strong>: Convert to Base58 using Bitcoin alphabet</li>
</ol>
<p><strong>Error Detection:</strong></p>
<ul>
<li>Double SHA256 provides ~32 bits of error detection</li>
<li>Probability of undetected error: ~1 in 4.3 billion</li>
<li>Single character errors are always detected</li>
<li>Most multi-character errors are detected</li>
</ul>
<p><strong>Character Set Benefits:</strong></p>
<ul>
<li>Excludes visually similar characters (0, O, I, l)</li>
<li>Case-sensitive for better error detection</li>
<li>58 characters provide good encoding efficiency</li>
<li>Human-readable and suitable for copy/paste</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>bufferKey</code></td>
<td class="type">
<span class="param-type">Buffer</span>
</td>
<td class="description last"><p>Binary data to encode (addresses, keys, etc.)</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_base58.js.html">src/utilities/base58.js</a>, <a href="src_utilities_base58.js.html#line146">line 146</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If input is not a valid Buffer</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If Base58 encoding fails (rare, usually indicates corruption)</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
</ul>
<h5>Returns:</h5>
<div class="param-desc">
<p>Base58Check encoded string with integrated checksum</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Encode a Bitcoin private key (WIF format)
const privateKeyBytes = Buffer.concat([
Buffer.from([0x80]), // Mainnet private key version
Buffer.from('e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35', 'hex'),
Buffer.from([0x01]) // Compressed public key flag
]);
const wifPrivateKey = b58encode(privateKeyBytes);
console.log(wifPrivateKey);
// "L5HgWvFghocq1FmxSjKNaGhVN8f67p6xYg5pY7M8FE77HXwHtGGu"</code></pre>
<pre class="prettyprint"><code>// Encode a Bitcoin address (P2PKH format)
const hash160 = Buffer.from('76a04053bda0a88bda5177b86a15c3b29f559873', 'hex');
const addressBytes = Buffer.concat([
Buffer.from([0x00]), // Mainnet P2PKH version
hash160 // RIPEMD160(SHA256(publicKey))
]);
const bitcoinAddress = b58encode(addressBytes);
console.log(bitcoinAddress);
// "1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH"</code></pre>
<pre class="prettyprint"><code>// Encode an extended public key (BIP32)
const extendedKeyData = Buffer.concat([
Buffer.from([0x04, 0x88, 0xb2, 0x1e]), // Mainnet xpub version
Buffer.from([0x00]), // Depth
Buffer.alloc(4, 0), // Parent fingerprint
Buffer.alloc(4, 0), // Child number
Buffer.from('873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508', 'hex'), // Chain code
Buffer.from('0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2', 'hex') // Public key
]);
const xpub = b58encode(extendedKeyData);
console.log(xpub);
// "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"</code></pre>
<pre class="prettyprint"><code>// Demonstrate checksum protection
const testData = Buffer.from('Hello Bitcoin!', 'utf8');
const encoded = b58encode(testData);
console.log('Encoded:', encoded);
// Checksum validation would catch corruption:
// If you modify any character in the encoded string, decoding will fail
// due to checksum mismatch, protecting against typos and transmission errors</code></pre>
<pre class="prettyprint"><code>// Compare with raw Base58 (no checksum)
const rawData = Buffer.from('test data', 'utf8');
const base58Only = binary_to_base58(Uint8Array.from(rawData));
const base58Check = b58encode(rawData);
console.log('Raw Base58:', base58Only); // Shorter, no error detection
console.log('Base58Check:', base58Check); // Longer, with checksum protection</code></pre>
<h4 class="name" id="base32_encode"><span class="type-signature"></span>base32_encode<span class="signature">(data)</span><span class="type-signature"> → {string}</span></h4>
<div class="description">
<p>Encodes 5-bit data values into Base32 string representation</p>
<p>This function converts an array of 5-bit values (0-31) into their
corresponding Base32 characters using the Bitcoin/CashAddr alphabet.
It's primarily used in the final step of Bech32 and CashAddr address
generation after data has been converted from 8-bit to 5-bit representation.</p>
<p><strong>Encoding Process:</strong></p>
<ol>
<li>Input: Array of 5-bit integers (values 0-31)</li>
<li>Mapping: Each value maps to corresponding character in CHARSET</li>
<li>Output: Concatenated string of Base32 characters</li>
</ol>
<p><strong>Use Cases:</strong></p>
<ul>
<li>Final encoding step for Bech32 SegWit addresses</li>
<li>Payload encoding in Bitcoin Cash CashAddr format</li>
<li>Checksum encoding for address validation</li>
<li>Custom data encoding with Bitcoin-compatible alphabet</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>data</code></td>
<td class="type">
<span class="param-type">Uint8Array</span>
|
<span class="param-type">Array.<number></span>
</td>
<td class="description last"><p>Array of 5-bit values (0-31) to encode</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_Base32.js.html">src/utilities/Base32.js</a>, <a href="src_utilities_Base32.js.html#line165">line 165</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If any input value is outside range 0-31</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If input is not array-like or is empty</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
</ul>
<h5>Returns:</h5>
<div class="param-desc">
<p>Base32-encoded string using Bitcoin alphabet</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Encode simple 5-bit values
const fiveBitData = new Uint8Array([0, 1, 2, 3, 4, 5]);
const encoded = base32_encode(fiveBitData);
console.log(encoded); // "qpzry9"
// Verify character mapping
console.log(encoded[0]); // "q" (index 0)
console.log(encoded[1]); // "p" (index 1)
console.log(encoded[2]); // "z" (index 2)</code></pre>
<pre class="prettyprint"><code>// Encode Bech32 address payload
// This would typically be the output of convertBits(hash, 8, 5)
const witnessProgram = new Uint8Array([
0, // Witness version
14, 8, 20, 6, 2, 8, 4, 21, 15, 12, 1, 1, 9, 25, 4, 11,
3, 23, 26, 10, 0, 31, 1, 15, 13, 26, 8, 21, 23, 4, 11, 2, 16
]);
const bech32Payload = base32_encode(witnessProgram);
console.log(bech32Payload);
// "qw508d6qejxtdg4y5r3zarvary0c5xw7k" (example P2WPKH payload)</code></pre>
<pre class="prettyprint"><code>// Encode CashAddr checksum
const checksumData = new Uint8Array([21, 15, 9, 14, 26, 20, 0, 15]);
const checksumString = base32_encode(checksumData);
console.log(checksumString); // "54n5063"</code></pre>
<pre class="prettyprint"><code>// Complete address generation workflow
function generateBech32Address(witnessVersion, witnessProgram) {
// Convert witness program from 8-bit to 5-bit
const converted = convertBits(witnessProgram, 8, 5);
// Prepend witness version
const data = new Uint8Array([witnessVersion, ...converted]);
// Calculate checksum (simplified)
const checksum = calculateBech32Checksum("bc", data);
// Encode payload and checksum
const payload = base32_encode(data);
const checksumStr = base32_encode(checksum);
return `bc1${payload}${checksumStr}`;
}</code></pre>
<pre class="prettyprint"><code>// Validation and round-trip testing
function validateEncoding() {
const testData = new Uint8Array(32); // 32 random 5-bit values
for (let i = 0; i < 32; i++) {
testData[i] = Math.floor(Math.random() * 32);
}
const encoded = base32_encode(testData);
console.log('Encoded length:', encoded.length); // Should equal testData.length
// Verify each character is in valid alphabet
for (const char of encoded) {
if (!CHARSET.includes(char)) {
throw new Error(`Invalid character in encoding: ${char}`);
}
}
console.log('✓ Encoding validation passed');
}</code></pre>
<h4 class="name" id="derive"><span class="type-signature"></span>derive<span class="signature">(path, key<span class="signature-attributes">opt</span>, serialization_format)</span><span class="type-signature"> → {<a href="global.html#DerivationResult">DerivationResult</a>}</span></h4>
<div class="description">
<p>Derives child keys from parent keys using BIP32 hierarchical deterministic algorithm</p>
<p>This function implements the complete BIP32 child key derivation specification:</p>
<p><strong>Derivation Process:</strong></p>
<ol>
<li><strong>Path Parsing</strong>: Converts BIP32 path notation (e.g., "m/0'/1/2") into numeric indices</li>
<li><strong>Hardened Detection</strong>: Identifies hardened derivation (') requiring private key access</li>
<li><strong>HMAC Computation</strong>: For each path component, computes HMAC-SHA512 with appropriate data</li>
<li><strong>Key Mathematics</strong>: Performs elliptic curve arithmetic to derive child keys</li>
<li><strong>Validation</strong>: Ensures derived keys are valid (non-zero, within curve order)</li>
<li><strong>Serialization</strong>: Updates metadata (depth, fingerprint, index) for child keys</li>
</ol>
<p><strong>Hardened vs Non-Hardened Derivation:</strong></p>
<ul>
<li><strong>Hardened (index ≥ 2³¹)</strong>: Uses private key in HMAC, breaks public key derivation chain</li>
<li><strong>Non-Hardened (index < 2³¹)</strong>: Uses public key in HMAC, allows public-only derivation</li>
</ul>
<p><strong>Security Implications:</strong></p>
<ul>
<li>Hardened derivation prevents compromise of parent from child key + chain code</li>
<li>Non-hardened allows watch-only wallets and public key derivation</li>
<li>BIP44 recommends hardened derivation for account-level and above</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>path</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
</td>
<td class="default">
</td>
<td class="description last"><p>BIP32 derivation path (e.g., "m/44'/0'/0'/0/0")</p></td>
</tr>
<tr>
<td class="name"><code>key</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
''
</td>
<td class="description last"><p>Parent extended key in xprv/xpub or tprv/tpub format</p></td>
</tr>
<tr>
<td class="name"><code>serialization_format</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="attributes">
</td>
<td class="default">
</td>
<td class="description last"><p>Parent key's serialization metadata</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_BIP32_derive.js.html">src/BIP32/derive.js</a>, <a href="src_BIP32_derive.js.html#line146">line 146</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>"Public Key can't derive from hardend path" - Attempting hardened derivation from public key</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If path format is invalid or contains non-numeric components</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If parent key format is invalid or corrupted</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If derived key is invalid (extremely rare: ~1 in 2^127)</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
</ul>
<h5>Returns:</h5>
<div class="param-desc">
<p>Tuple of [derived keys, child serialization format]</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="global.html#DerivationResult">DerivationResult</a></span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Standard BIP44 Bitcoin account derivation
import { fromSeed } from './fromSeed.js';
const seed = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
const [masterKeys, masterFormat] = fromSeed(seed, "main");
// Derive account 0, change 0, address 0
const [accountKeys, accountFormat] = derive("m/44'/0'/0'", masterKeys.HDpri, masterFormat);
const [changeKeys, changeFormat] = derive("m/0", accountKeys.HDpri, accountFormat);
const [addressKeys, addressFormat] = derive("m/0", changeKeys.HDpri, changeFormat);
console.log("Final address key:", addressKeys.HDpub);</code></pre>
<pre class="prettyprint"><code>// Public key derivation (non-hardened only)
const [publicDerived, _] = derive("m/0/1/2", masterKeys.HDpub, masterFormat);
console.log("Public-derived key:", publicDerived.HDpub);
console.log("Private key:", publicDerived.HDpri); // null - no private key available</code></pre>
<pre class="prettyprint"><code>// Multi-level derivation with error handling
try {
// This will fail - can't derive hardened from public key
const [failed, _] = derive("m/0'", masterKeys.HDpub, masterFormat);
} catch (error) {
console.log(error.message); // "Public Key can't derive from hardend path"
}</code></pre>
<pre class="prettyprint"><code>// Complex derivation path
const complexPath = "m/49'/0'/0'/0/0"; // BIP49 P2SH-wrapped SegWit
const [segwitKeys, segwitFormat] = derive(complexPath, masterKeys.HDpri, masterFormat);
// Access derived key components
console.log("Depth:", segwitFormat.depth); // 5
console.log("Child index:", segwitFormat.childIndex); // 0
console.log("Parent fingerprint:", segwitFormat.parentFingerPrint.toString('hex'));</code></pre>
<pre class="prettyprint"><code>// Iterative derivation for address generation
let currentKeys = masterKeys;
let currentFormat = masterFormat;
const pathComponents = ["44'", "0'", "0'", "0"];
for (const component of pathComponents) {
[currentKeys, currentFormat] = derive(`m/${component}`, currentKeys.HDpri, currentFormat);
}
// Generate first 10 addresses
for (let i = 0; i < 10; i++) {
const [addrKeys, _] = derive(`m/${i}`, currentKeys.HDpri, currentFormat);
console.log(`Address ${i}:`, addrKeys.HDpub);
}</code></pre>
<h4 class="name" id="fromSeed"><span class="type-signature"></span>fromSeed<span class="signature">(seed, net<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {<a href="global.html#MasterKeyResult">MasterKeyResult</a>}</span></h4>
<div class="description">
<p>Generates BIP32 master keys from a cryptographic seed</p>
<p>This function implements the BIP32 master key generation algorithm:</p>
<ol>
<li><strong>HMAC-SHA512 Computation</strong>: Uses "Bitcoin seed" as HMAC key and input seed as data</li>
<li><strong>Key Material Split</strong>: Divides 512-bit result into 256-bit private key (IL) and 256-bit chain code (IR)</li>
<li><strong>Validation</strong>: Ensures IL is valid (non-zero and less than curve order)</li>
<li><strong>Public Key Derivation</strong>: Computes corresponding compressed public key</li>
<li><strong>Serialization</strong>: Creates extended key format with network-specific version bytes</li>
</ol>
<p>The master keys serve as the root of the entire HD key tree, allowing deterministic
derivation of billions of child keys while maintaining mathematical relationships
between them for features like watch-only wallets and audit capabilities.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>seed</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
</td>
<td class="default">
</td>
<td class="description last"><p>Hex-encoded cryptographic seed (typically 128-512 bits from BIP39)</p></td>
</tr>
<tr>
<td class="name"><code>net</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
'main'
</td>
<td class="description last"><p>Network type: 'main' for Bitcoin mainnet, 'test' for testnet</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_BIP32_fromSeed.js.html">src/BIP32/fromSeed.js</a>, <a href="src_BIP32_fromSeed.js.html#line128">line 128</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If seed results in invalid private key (extremely rare: ~1 in 2^127)</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If seed is not valid hexadecimal</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If network parameter is not recognized</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
</ul>
<h5>Returns:</h5>
<div class="param-desc">
<p>Tuple containing [HD key pair, serialization format]</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="global.html#MasterKeyResult">MasterKeyResult</a></span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Generate master keys from BIP39 seed
const seed = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
const [hdKeys, format] = fromSeed(seed, "main");
console.log(hdKeys.HDpri);
// "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
console.log(hdKeys.HDpub);
// "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"</code></pre>
<pre class="prettyprint"><code>// Generate testnet master keys
const [testKeys, testFormat] = fromSeed(seed, "test");
console.log(testKeys.HDpri.substring(0, 4)); // "tprv" (testnet prefix)
console.log(testKeys.HDpub.substring(0, 4)); // "tpub" (testnet prefix)</code></pre>
<pre class="prettyprint"><code>// Use with BIP39 mnemonic-derived seed
import { bip39 } from '../BIP39/bip39.js';
const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
const bip39Seed = bip39.mnemonic2seed(mnemonic, "passphrase");
const [masterKeys, _] = fromSeed(bip39Seed, "main");</code></pre>
<pre class="prettyprint"><code>// Access internal key material for advanced operations
const [_, format] = fromSeed(seed, "main");
console.log(format.privKey.key.toString('hex')); // Raw 32-byte private key
console.log(format.pubKey.key.toString('hex')); // Compressed 33-byte public key
console.log(format.chainCode.toString('hex')); // Chain code for child derivation</code></pre>
<h4 class="name" id="hdKey"><span class="type-signature"></span>hdKey<span class="signature">(keyType, params)</span><span class="type-signature"> → {string}</span></h4>
<div class="description">
<p>Encodes hierarchical deterministic keys according to BIP32 specification</p>
<p>This function creates extended keys (xprv/xpub, tprv/tpub) that contain not only
the key material but also metadata necessary for hierarchical key derivation:</p>
<p><strong>Extended Key Structure (78 bytes total):</strong></p>
<ul>
<li>4 bytes: Version (network and key type identifier)</li>
<li>1 byte: Depth (number of derivations from master)</li>
<li>4 bytes: Parent fingerprint (first 4 bytes of parent key hash)</li>
<li>4 bytes: Child index (derivation index used)</li>
<li>32 bytes: Chain code (for deriving child keys)</li>
<li>33 bytes: Key data (private key with 0x00 prefix OR compressed public key)</li>
</ul>
<p><strong>Network Prefixes:</strong></p>
<ul>
<li>Mainnet: xprv/xpub (starts with "xprv9" or "xpub6")</li>
<li>Testnet: tprv/tpub (starts with "tprv8" or "tpub8")</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>keyType</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="default">
pri
</td>
<td class="description last"><p>Key type: 'pri' for private key, 'pub' for public key</p></td>
</tr>
<tr>
<td class="name"><code>params</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="default">
</td>
<td class="description last"><p>BIP32 serialization parameters</p>
<h6>Properties</h6>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>versionByte</code></td>
<td class="type">
<span class="param-type"><a href="global.html#VersionBytes">VersionBytes</a></span>
</td>
<td class="description last"><p>Network-specific version bytes</p></td>
</tr>
<tr>
<td class="name"><code>depth</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last"><p>Derivation depth (0-255)</p></td>
</tr>
<tr>
<td class="name"><code>parentFingerPrint</code></td>
<td class="type">
<span class="param-type">Buffer</span>
</td>
<td class="description last"><p>4-byte parent key fingerprint</p></td>
</tr>
<tr>
<td class="name"><code>childIndex</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last"><p>Child derivation index (0 to 2^32-1)</p></td>
</tr>
<tr>
<td class="name"><code>chainCode</code></td>
<td class="type">
<span class="param-type">Buffer</span>
</td>
<td class="description last"><p>32-byte chain code for child derivation</p></td>
</tr>
<tr>
<td class="name"><code>privKey</code></td>
<td class="type">
<span class="param-type"><a href="global.html#PrivateKeyInfo">PrivateKeyInfo</a></span>
</td>
<td class="description last"><p>Private key information (required for 'pri' type)</p></td>
</tr>
<tr>
<td class="name"><code>pubKey</code></td>
<td class="type">
<span class="param-type"><a href="global.html#PublicKeyInfo">PublicKeyInfo</a></span>
</td>
<td class="description last"><p>Public key information (required for 'pub' type)</p></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_encodeKeys.js.html">src/utilities/encodeKeys.js</a>, <a href="src_utilities_encodeKeys.js.html#line149">line 149</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If keyType is neither 'pri' nor 'pub'</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If required key information is missing for specified type</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If serialization parameters are invalid or malformed</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
</li>
</ul>
<h5>Returns:</h5>
<div class="param-desc">
<p>Base58Check-encoded extended key</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Create extended private key (xprv)
const masterFormat = {
versionByte: { privKey: 0x0488ade4, pubKey: 0x0488b21e },
depth: 0,
parentFingerPrint: Buffer.alloc(4, 0),
childIndex: 0,
chainCode: Buffer.from('873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508', 'hex'),
privKey: {
key: Buffer.from('e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35', 'hex'),
versionByteNum: 0x80
},
pubKey: {
key: Buffer.from('0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2', 'hex')
}
};
const xprv = hdKey('pri', masterFormat);
console.log(xprv);
// "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"</code></pre>
<pre class="prettyprint"><code>// Create extended public key (xpub)
const xpub = hdKey('pub', masterFormat);
console.log(xpub);
// "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"</code></pre>
<pre class="prettyprint"><code>// Create testnet extended keys
const testnetFormat = { ...masterFormat };
testnetFormat.versionByte = { privKey: 0x04358394, pubKey: 0x043587cf };
const tprv = hdKey('pri', testnetFormat);
const tpub = hdKey('pub', testnetFormat);
console.log(tprv.substring(0, 4)); // "tprv"
console.log(tpub.substring(0, 4)); // "tpub"</code></pre>
<pre class="prettyprint"><code>// Child key with derivation metadata
const childFormat = {
versionByte: { privKey: 0x0488ade4, pubKey: 0x0488b21e },
depth: 3, // 3rd level derivation
parentFingerPrint: Buffer.from([0x5c, 0x1b, 0xd6, 0x48]), // Parent fingerprint
childIndex: 2147483647, // Hardened derivation (2^31 - 1)
chainCode: Buffer.from('47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141', 'hex'),
privKey: {
key: Buffer.from('cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca', 'hex'),
versionByteNum: 0x80
},
pubKey: {
key: Buffer.from('0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2', 'hex')
}
};
const childXprv = hdKey('pri', childFormat);
// This will produce an extended key reflecting the derivation path and depth</code></pre>
<h4 class="name" id="legacyAddress_decode"><span class="type-signature"></span>legacyAddress_decode<span class="signature">(legacy_addr<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {Uint8Array}</span></h4>
<div class="description">
<p>Decodes a legacy Bitcoin address to extract the HASH160 value</p>
<p>Legacy Bitcoin addresses use Base58Check encoding to represent the HASH160
of a public key or script. This function extracts the raw 20-byte hash
from P2PKH (Pay to Public Key Hash) addresses, which is essential for
address validation, conversion, and payment processing.</p>
<p><strong>Legacy Address Structure:</strong></p>
<ul>
<li>1 byte: Version byte (0x00 mainnet P2PKH, 0x6f testnet P2PKH, 0x05 mainnet P2SH, etc.)</li>
<li>20 bytes: HASH160 value (RIPEMD160(SHA256(pubkey)) for P2PKH)</li>
<li>4 bytes: Checksum (first 4 bytes of double SHA256)</li>
</ul>
<p><strong>Address Types by Version:</strong></p>
<ul>
<li>0x00: Mainnet P2PKH (starts with "1")</li>
<li>0x05: Mainnet P2SH (starts with "3")</li>
<li>0x6f: Testnet P2PKH (starts with "m" or "n")</li>
<li>0xc4: Testnet P2SH (starts with "2")</li>
</ul>
<p>The function focuses on P2PKH addresses but can decode any 25-byte legacy
address format to extract the central hash value.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>legacy_addr</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
"1EiBTNS9Dqhjhk7D78GMAjK9pZn5NXZf91"
</td>
<td class="description last"><p>Base58Check encoded legacy address</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_utilities_decodeKeys.js.html">src/utilities/decodeKeys.js</a>, <a href="src_utilities_decodeKeys.js.html#line269">line 269</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<ul>
<li>
<dl>
<dt>
<div class="param-desc">
<p>If address format is invalid or corrupted</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>