bitcoinjs/bitcoinjs-lib

Prefix xpub to dgub[bug]

PlazaFer opened this issue · 1 comments

Hello, how are you? I have an issue that I can't solve. Through bitcoinjs-lib, I'm obtaining and generating dodge addresses, as well as public and private keys. The problem is that I get the public key as xpub, and the backend requires it with the dgub prefix instead of xpub. Alternatively, I might need to convert it from xpub to dgub. Could you assist me with this? Thanks!
Here, I'm sharing the code that obtains addresses and keys for Dodge and other currencies. Additionally, I'm providing the derivation path I'm using for Dodge.

Derivations path for Dodgecoin

derivationPath: "m/44'/3'/0'/0/0",
  rootDerivation: "m/44'/3'/0'",

File

import { Network as BTCNetwork, payments } from 'bitcoinjs-lib';
import { HDNode } from 'ethers/lib/utils';
import b58 from 'bs58check';
import { btcNetworks, btcNetworksTestnet } from '../constants/predefinedNetworks';
import { WalletNetworkData } from '../stores/wallets';
import { BTCAddressType } from '../types/networks';
import bchaddr from 'bchaddrjs';

const convertXpubToZpub = (xpub: string) => {
  let data = b58.decode(xpub);
  data = data.slice(4);
  data = Buffer.concat([Buffer.from('04b24746', 'hex'), data]);
  return b58.encode(data);
};

export const convertZpubXoZpub = (xpub: string) => {
  let data = b58.decode(xpub);
  data = data.slice(4);
  data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
  return b58.encode(data);
};

export const getBtcAddressFromPublicKey = (params: {
  publicKey: string;
  addressType: BTCAddressType;
  networkData: BTCNetwork;
}) => {
  const { publicKey, networkData, addressType } = params;

  const { address } = payments[addressType]({ pubkey: Buffer.from(publicKey, 'hex'), network: networkData });

  // Special case BCH ADDRESS PARSE TO CashAddr Format
  if (networkData.messagePrefix === '\x18Bitcoin Cash Signed Message:\n') {
    return bchaddr.toCashAddress(address) || address;
  }

  return address;
};

export const getAllBtcNetworksAddresses = (params: { node: HDNode }) => {
  const { node } = params;

  const addresses: { [key in string]: string } = {};
  const networks: { [key in string]: WalletNetworkData } = {};

  [...btcNetworks, ...btcNetworksTestnet].forEach((network) => {
    const derivatedNode = node.derivePath(network.derivationPath)
    const accountKeys = node
      .derivePath((network as any).rootDerivation || network.derivationPath.replace(`/0/0`, ''))
      .neuter();

    const convertNodeToAddress = (nodeEthers: HDNode) => {
      const publicKey = nodeEthers.publicKey.replace('0x', '');

      return {
        path: nodeEthers.path,
        publicKey,
        address: getBtcAddressFromPublicKey({
          publicKey,
          addressType: network.addressType,
          networkData: network.networkData,
        }) as string,
      };
    };

    const publicKey = derivatedNode.publicKey.replace('0x', '');
    const { address } = convertNodeToAddress(derivatedNode);

    if (!address) throw new Error('Error while generating address');

    networks[network.walletId] = {
      address,
      publicKey,
      privateKey: derivatedNode.privateKey.replace('0x', ''),
      extendedPublicKey: network.derivationPath.startsWith(`m/44`)
        ? accountKeys.extendedKey
        : convertXpubToZpub(accountKeys.extendedKey),
      extendedPrivateKey: derivatedNode.extendedKey,
      utxos: {
        internal: Object.fromEntries(
          Array.from({ length: 1 })
            .map((_, index) => accountKeys.derivePath(`1/${index}`))
            .map(convertNodeToAddress)
            .entries()
        ),
        external: Object.fromEntries(
          Array.from({ length: 1 })
            .map((_, index) => accountKeys.derivePath(`0/${index}`))
            .map(convertNodeToAddress)
            .entries()
        ),
      },
    };
  });

  return { addresses, networks };
};

You need to use the version for dgub which is easily found in many places such as the coininfo package.

https://github.com/cryptocoinjs/coininfo/blob/e744f1caf1529e7feccd98aac889214dc2bd2cc7/lib/coins/doge.js#L19-L22