Untitled
unknown
plain_text
a year ago
3.8 kB
10
Indexable
declare enum AddressType {
p2pkh = "p2pkh",
p2sh = "p2sh",
p2wpkh = "p2wpkh",
p2wsh = "p2wsh",
p2tr = "p2tr"
}
const networkModes = ['mainnet', 'testnet'] as const;
type NetworkModes = (typeof networkModes)[number];
const getCoinType = (network: NetworkModes) => (network === 'mainnet' ? 0 : 1);
const walletTypes = [
{ type: 'Native Segwit', path: `m/84'/`, addressType: AddressType.p2wpkh },
{ type: 'Nested Segwit', path: `m/49'/`, addressType: AddressType.p2sh },
{ type: 'Legacy', path: `m/44'/`, addressType: AddressType.p2pkh },
{ type: 'Taproot', path: `m/86'/`, addressType: AddressType.p2tr },
];
function getPublicKeyFromXpubAtIndex(xpub: string, index: number, network: string): Buffer {
const btcNetwork = network === 'mainnet' ? networks.bitcoin : networks.testnet;
const { publicKey } = bip32.fromBase58(xpub, btcNetwork).derivePath(`0/${index}`);
return Buffer.from(publicKey);
}
function publicKeyToAddress(publicKey: string, type: AddressType, network: Network) {
if (!publicKey) return '';
const pubkey = Buffer.from(publicKey, 'hex');
if (type === AddressType.p2pkh) {
const { address } = bitcoin.payments.p2pkh({
pubkey,
network,
});
return address || '';
} else if (type === AddressType.p2wpkh) {
const { address } = bitcoin.payments.p2wpkh({
pubkey,
network,
});
return address || '';
} else if (type === AddressType.p2tr) {
const { address } = bitcoin.payments.p2tr({
internalPubkey: pubkey.length === 32 ? pubkey : pubkey.slice(1, 33),
network,
});
return address || '';
} else if (type === AddressType.p2sh) {
const { address } = bitcoin.payments.p2sh({
pubkey: pubkey,
network,
redeem: bitcoin.payments.p2wpkh({ pubkey: pubkey, network }),
});
return address || '';
} else {
return '';
}
}
async function importAccointFromLedger({
extendedPublicKey,
network,
addressIndex,
addressType,
}: {
extendedPublicKey: string;
network: NetworkModes;
addressIndex: number;
addressType: AddressType;
}): Promise<{ address: string; publicKey: string }> {
const publicKey = getPublicKeyFromXpubAtIndex(extendedPublicKey, addressIndex, network).toString(
'hex'
);
const net = network === 'mainnet' ? networks.bitcoin : networks.testnet;
const address = publicKeyToAddress(publicKey, addressType, net);
return { address, publicKey: publicKey };
}
export function pullBitcoinKeysFromLedgerDevice(
app: BitcoinApp,
derivationPath: string,
addressType: AddressType
) {
return async ({ onRequestKey, network }) => {
const amountOfKeysToExtractFromDevice = 10;
const btcNetwork = getCoinType(network);
const keys: IAddressSelection[] = [];
for (let accountIndex = 0; accountIndex < amountOfKeysToExtractFromDevice; accountIndex++) {
const xpubDerivationPath = `${derivationPath}${btcNetwork}'/${accountIndex}'`;
const extendedPublicKey = await app.getExtendedPubkey(xpubDerivationPath);
onRequestKey?.(accountIndex);
const { publicKey, address } = await importAccointFromLedger({
extendedPublicKey,
network,
addressIndex: 0,
addressType,
});
const fullDerivationPath = `${xpubDerivationPath}/0/0`;
keys.push({
publicKey,
address,
xpub: extendedPublicKey,
derivationPath: fullDerivationPath,
});
}
return { status: 'success', keys };
};
}
Editor is loading...
Leave a Comment