2

I see a lot of JavaScript Base58 encoder functions online, but all of them seem to require node. Is there a simple JavaScript Base58 encoder that will just run in the browser without any node installation or modification?

1 Answer 1

2

Here's a pure javascript base58 encoder fuction I helped put together. Included are some comments that helped me understand what is going on beyond the barebones functions you can find elsewhere.

function encode_b58(hex_number) {
    // Set of base58 chars (Note: there is no '0','O','I' or 'l').
    const base58 = [1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
    //Take input string of hexadecimal bytes and convert it to a base 10
    //decimal number. BigInt needed as regular JS numbers don't represent enough significant digits.
    var num = BigInt('0x' + hex_number);
    //Our very large number will be repeatedly divided by 58.
    const fifty8 = BigInt(58);
    //The remainder of this division will be a number (0-57).
    var remainder;
    //Each remainder's value maps to a character in our base58 array, and
    //the string of these characters becomes our Base58 encoded output.
    var b58_encoded_buffer = '';
    //We move from: Hex Bytes -> Decimal Number -> Base58 Encoded string.
    //To move through each place value of a base58 number, we continue to
    //divide by 58, until the integer number rounds down to 0.
    while (num > 0) {
        //The modulus operator returns our remainder, which depends on
        //the least significant digit in our BigInt converted input.
        //For example: if we were doing modulo 2 division, all odd
        //numbers - regardless of how long they are - would return a
        //remainder of 1, because the least significant digit is odd.
        remainder = num % fifty8;

        //Thus, we're encoding the right most (lowest place value)
        //digits first, and so each subsequently encoded character
        //needs to be added to the left of our encoded buffer
        //so that the beginning & end of our input string/bytes aligns
        //with the beginning & end of our Base58 encoded output.
        b58_encoded_buffer = base58[remainder] + b58_encoded_buffer;

        //Dividing by 58 gives us our quotient (rounded down to the
        //nearest integer), and moves us over one base58 place value,
        //ready for the next round of b58 division/mapping/encoding.
        num = num/BigInt(58);
    }

    //When we convert our byte-based hex input into a base 10 number, we
    //lose the leading zero bytes in the converted decimal number.
    //For example, if our hex input converted into the decimal number
    //000017, this number would be reduced automatically to 17 in base10,
    //and so we'd lose the leading zeros, which aren't important
    //when doing base 10 math, but are important in preserving the
    //information held in our original input value. So, in order to not
    //lose the leading zeros, we count them, and then prepend them (as
    //1's, which is their corresponding base58 value) to the beginning
    //of our Base58 encoded output string.
    while ( hex_number.match(/^00/) ){
        //For each leading zero byte, add a '1' to the encoded output.
        b58_encoded_buffer = '1' + b58_encoded_buffer;
        //And remove the leading zero byte, and test for another.
        hex_number = hex_number.substring(2);
    }

    return b58_encoded_buffer;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.