pingql/apps/pay/src/address.ts

59 lines
2.2 KiB
TypeScript

/// HD address derivation using bitcore-lib family.
/// Derives child addresses at m/0/{index} (external receive chain).
// @ts-ignore
import bitcore from "bitcore-lib";
import bs58check from "bs58check";
// @ts-ignore
import bitcoreCash from "bitcore-lib-cash";
// @ts-ignore
import bitcoreLtc from "bitcore-lib-ltc";
// @ts-ignore
import bitcoreDoge from "bitcore-lib-doge";
// @ts-ignore
import dashcore from "@dashevo/dashcore-lib";
function getXpub(coin: string): string {
const key = `XPUB_${coin.toUpperCase()}`;
const val = process.env[key];
if (!val) throw new Error(`Missing env var: ${key}`);
return val;
}
export function derive(coin: string, index: number): string {
const xpub = getXpub(coin === "xec" ? "xec" : coin);
if (coin === "btc") {
const hd = new bitcore.HDPublicKey(xpub);
return hd.deriveChild(0).deriveChild(index).publicKey.toAddress().toString();
}
if (coin === "bch") {
const hd = new bitcoreCash.HDPublicKey(xpub);
return hd.deriveChild(0).deriveChild(index).publicKey.toAddress().toCashAddress();
}
if (coin === "xec") {
const hd = new bitcoreCash.HDPublicKey(xpub);
const addr = hd.deriveChild(0).deriveChild(index).publicKey.toAddress().toCashAddress();
return addr.replace(/^bitcoincash:/, "ecash:");
}
if (coin === "ltc") {
// Remap zpub/Ltub/Mtub to standard xpub version bytes for bitcore-lib-ltc
const decoded = Buffer.from(bs58check.decode(xpub));
decoded[0] = 0x04; decoded[1] = 0x88; decoded[2] = 0xb2; decoded[3] = 0x1e;
const normalized = bs58check.encode(decoded);
const hd = new bitcoreLtc.HDPublicKey(normalized);
const pubkey = hd.deriveChild(0).deriveChild(index).publicKey;
return new bitcoreLtc.Address(pubkey, bitcoreLtc.Networks.mainnet, bitcoreLtc.Address.PayToWitnessPublicKeyHash).toString();
}
if (coin === "doge") {
const hd = new bitcoreDoge.HDPublicKey(xpub);
return hd.deriveChild(0).deriveChild(index).publicKey.toAddress().toString();
}
if (coin === "dash") {
const hd = new dashcore.HDPublicKey(xpub);
return hd.deriveChild(0).deriveChild(index).publicKey.toAddress().toString();
}
throw new Error(`Unsupported coin: ${coin}`);
}