Greetings.
I'am developing a crypto wallet in Javascript and the first coin that I want to have in my wallet is bitcoin.
My code is working, I do generate an address that is 25 byte long.
How I proceed;
In NodeJS
Create a mnemonic with BIP39
Use it has a seed.
Then I use a npm package
https://www.npmjs.com/package/hdkey. Its a lib to produce a BIP32 key pair that I have to look more into.
To produce the master keys.
I then create public keys from the master key
Hash it once and passing RIPMD160
I add the prefix.
Hash twice to get the checksum and add the checksum at the end of prefixed address
Then I pass it in base58 encoder.
I end up with an adress that looks good but when I try to validate my adress I get a bad digest error msg.
It's been 3 days now and I can't figure what is not working.
Some validation tool are reporting bad digest or bad checksum but how can I validate?
Please help.
Here is my code;
const bip39 = require('bip39');
const hdkey = require('hdkey');
const createHash = require('create-hash/browser');
const Buffer = require('buffer').Buffer;
const bs58check = require('bs58');
/// BIP39 SEED
/// https://www.npmjs.com/package/bip39
//const mnemonic = bip39.generateMnemonic();
const mnemonic ="tag observe slush wheel verb uncover evolve old refuse shoot swarm camera";
const seed = bip39.mnemonicToSeedSync(mnemonic);
//console.log(bip39.mnemonicToSeed(mnemonic));
// const seed = bip39.mnemonicToSeed('basket actual').then(bytes => bytes.toString('hex'))
console.log('Mnemonic : ',mnemonic);
console.log('Seed : ',seed.toString('hex'));
/// HDKEY
/// https://www.npmjs.com/package/hdkey
const root = hdkey.fromMasterSeed(new Buffer(seed, 'hex'));
const masterPrivateKey = root.privateKey.toString('hex');
console.log('Master Private : ' , masterPrivateKey);
/// COIN REGISTRATION
/// https://github.com/satoshilabs/docs/blob/bdd9fd92386827bfa031a88c10e3e6fd834d56e3/slips/slip-0044.rst
/// BITCOIN ADRESS TYPE
const addrnode = root.derive("m/44'/0'/0'/0/0");
// console.log('hdkey pbx : ' ,root.publicExtendedKey);
/// Private and Public Key
const rawPbK = Buffer.from(addrnode._publicKey);
const rawPvK = addrnode._privateKey;
/// Hashing the raw publiv key
const hash1pbk = createHash('sha256').update(rawPbK).digest();
const hash1rmd = createHash('rmd160').update(hash1pbk).digest();
console.log('Raw Public Key : ' ,rawPbK.toString('hex'));
// Space allocation
var pubAddr = Buffer.allocUnsafe(21);
// Adding testnet prefix
pubAddr.writeUInt8(0x00, 0);
// Copying the public adress tafter the prefix?
hash1rmd.copy(pubAddr, 1);
console.log('Address Buffer : ' ,pubAddr.toString('hex'));
const hash2 = createHash('sha256').update(hash1rmd).digest();
const hash3 = createHash('sha256').update(hash2).digest();
console.log('Hash 3 : ' ,hash3.toString('hex'));
// 4 first byte of the last hash for checksum
const chksum = hash3.slice(0,4);
console.log('4 first bytes Checksum : ' ,chksum);
/// Adding checksum to prefix Adress
const address = Buffer.concat([pubAddr,chksum]);
console.log('Public Adress : ' ,address);
/// BASE 58
/// https://www.npmjs.com/package/base-58
const pbAddr = bs58check.encode(address);
console.log('BASE58 ADDRESS : ' ,pbAddr);
This is my output in the console;
Mnemonic : tag observe slush wheel verb uncover evolve old refuse shoot swarm camera
Seed : f550bc2bc355998e74cd2116a104fdd8a1fe0d0b7e64826b5d14a470e6d1e2be2b991fd2607cd8d
fc3ca435f351b346586faac8b20e945326f823c3ef5c60859
Master Private : 14ab6a6abed95d30420a1b9eb9ab7f6f7447b5255ca3d46c099d7b325fa7f1f3
Raw Public Key : 03b30574120027d4f51edb1cfc323d197aba3fe5e86c85cbbfc8946a4dbf55fa2b
Address Buffer : 003683f0d40e5cfb112e9055f792204e58614815f4
Hash 3 : 1b80d052329097dfb65beb34b2cf9fb5f00bd558ad3379e3428536ded1940cc3
4 first bytes Checksum : 1b80d052
Public Adress : 003683f0d40e5cfb112e9055f792204e58614815f41b80d052
BASE58 ADDRESS : 15yFYmBx7cWYhsjNh7EMDM5tw2JnzBNYtZ
Thank you for your time!