Last active
April 24, 2024 14:55
-
-
Save jaonoctus/db0f07aba4d2277be4ecb411b44f93d3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var base58 = require('bs58') | |
var { sha256 } = require('@noble/hashes/sha256') | |
const useBs58check = function (checksumFn) { | |
// Encode a buffer as a base58-check encoded string | |
function encode (payload) { | |
var payloadU8 = Uint8Array.from(payload) | |
var checksum = checksumFn(payloadU8) | |
var length = payloadU8.length + 4 | |
var both = new Uint8Array(length) | |
both.set(payloadU8, 0) | |
both.set(checksum.subarray(0, 4), payloadU8.length) | |
return base58.encode(both, length) | |
} | |
function decodeRaw (buffer) { | |
var payload = buffer.slice(0, -4) | |
var checksum = buffer.slice(-4) | |
var newChecksum = checksumFn(payload) | |
if (checksum[0] ^ newChecksum[0] | | |
checksum[1] ^ newChecksum[1] | | |
checksum[2] ^ newChecksum[2] | | |
checksum[3] ^ newChecksum[3]) return | |
return payload | |
} | |
// Decode a base58-check encoded string to a buffer, no result if checksum is wrong | |
function decodeUnsafe (string) { | |
var buffer = base58.decodeUnsafe(string) | |
if (!buffer) return | |
return decodeRaw(buffer) | |
} | |
function decode (string) { | |
var buffer = base58.decode(string) | |
var payload = decodeRaw(buffer, checksumFn) | |
if (!payload) throw new Error('Invalid checksum') | |
return payload | |
} | |
return { | |
encode: encode, | |
decode: decode, | |
decodeUnsafe: decodeUnsafe | |
} | |
} | |
function doubleSha256 (buffer) { | |
return sha256(sha256(buffer)) | |
} | |
const bs58check = useBs58check(doubleSha256) | |
/* | |
This script uses version bytes as described in SLIP-132 | |
https://github.com/satoshilabs/slips/blob/master/slip-0132.md | |
*/ | |
const prefixes = new Map([ | |
['xpub', '0488b21e'], | |
['ypub', '049d7cb2'], | |
['Ypub', '0295b43f'], | |
['zpub', '04b24746'], | |
['Zpub', '02aa7ed3'], | |
['tpub', '043587cf'], | |
['upub', '044a5262'], | |
['Upub', '024289ef'], | |
['vpub', '045f1cf6'], | |
['Vpub', '02575483'], | |
]) | |
/* | |
* This function takes an extended public key (with any version bytes, it doesn't need to be an xpub) | |
* and converts it to an extended public key formatted with the desired version bytes | |
* @param xpub: an extended public key in base58 format. Example: xpub6CpihtY9HVc1jNJWCiXnRbpXm5BgVNKqZMsM4XqpDcQigJr6AHNwaForLZ3kkisDcRoaXSUms6DJNhxFtQGeZfWAQWCZQe1esNetx5Wqe4M | |
* @param targetFormat: a string representing the desired prefix; must exist in the "prefixes" mapping defined above. Example: Zpub | |
*/ | |
function changeVersionBytes(xpub, targetFormat) { | |
if (!prefixes.has(targetFormat)) { | |
return 'Invalid target version' | |
} | |
// trim whitespace | |
xpub = xpub.trim() | |
try { | |
var data = bs58check.decode(xpub) | |
data = data.slice(4) | |
data = Buffer.concat([Buffer.from(prefixes.get(targetFormat), 'hex'), data]) | |
data = bs58check.encode(data) | |
return data | |
} catch (err) { | |
return 'Invalid extended public key' | |
} | |
} | |
// example | |
const input = 'zpub6rD5AGSXPTDMSnpmczjENMT3NvVF7q5MySww6uxitUsBYgkZLeBywrcwUWhW5YkeY2aS7xc45APPgfA6s6wWfG2gnfABq6TDz9zqeMu2JCY' | |
changeVersionBytes(input, 'xpub') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment