@blockchain-api/bitcoin-js
Version:
Blockchain Api Bitcoin JS
117 lines (110 loc) • 4.4 kB
text/typescript
import { mnemonicToSeed } from 'bip39'
import { fromBase58, fromSeed } from 'bip32'
import { payments, ECPair, address as asdressUtils, Network } from 'bitcoinjs-lib'
import { Transaction } from 'bitcore-lib'
import { UTXO } from '../interfaces/UTXO'
/**
* Generate Bitcoin wallet
* @param testnet testnet or mainnet version of address
* @param mnemonic mnemonic seed to use
* @returns wallet
*/
export const generateWallet = async (mnemonic: string, path: string, network: Network): Promise<{ mnemonic: string, accountExtPubkey: string, accountExtPrivatekey: string, bip32ExtPubkey: string, bip32ExtPrivatekey: string }> => {
const seedBuffer = await mnemonicToSeed(mnemonic)
const hdwallet = fromSeed(seedBuffer, network)
const bip32Interface = hdwallet.derivePath(path)
return {
mnemonic: mnemonic,
accountExtPubkey: bip32Interface.neutered().toBase58(),
accountExtPrivatekey: bip32Interface.toBase58(),
bip32ExtPubkey: bip32Interface.derive(0).neutered().toBase58(),
bip32ExtPrivatekey: bip32Interface.derive(0).toBase58(),
}
}
/**
* Generate Bitcoin address from mnemonic
* @param testnet testnet or mainnet version of address
* @param mnemonic mnemonic seed to use
* @param i derivation index of address to generate. Up to 2^31 addresses can be generated.
* @returns blockchain address
*/
export const generateAddressFromMnemonic = async (path: string, mnemonic: string, i: number, network: Network) => {
const wallet = await generateWallet(mnemonic, path, network)
const w = fromBase58(wallet.bip32ExtPubkey, network).derivePath(String(i))
return payments.p2pkh({ pubkey: w.publicKey, network }).address as string
}
/**
* Convert Bitcoin Private Key to Address
* @param testnet testnet or mainnet version of address
* @param privkey private key to use
* @returns blockchain address
*/
export const generateAddressFromPrivatekey = (privkey: string, network: Network) => {
const keyPair = ECPair.fromWIF(privkey, network)
return payments.p2pkh({ pubkey: keyPair.publicKey, network }).address as string
}
/**
* Generate Bitcoin private key from mnemonic seed
* @param testnet testnet or mainnet version of address
* @param mnemonic mnemonic to generate private key from
* @param i derivation index of private key to generate.
* @returns blockchain private key to the address
*/
export const generatePrivateKeyFromMnemonic = async (mnemonic: string, path: string, i: number, network: Network) => {
return fromSeed(await mnemonicToSeed(mnemonic), network)
.derivePath(path)
.derive(i)
.toWIF()
}
/**
* Generate address from xpub
* @param currency type of blockchain
* @param testnet testnet or mainnet version of address
* @param xpub extended public key to generate address from
* @param i derivation index of address to generate. Up to 2^31 addresses can be generated.
* @returns blockchain address
*/
export const generateAddressFromXPub = (xpub: string, i: number, network: Network) => {
const w = fromBase58(xpub, network).derivePath(String(i))
return payments.p2pkh({ pubkey: w.publicKey, network }).address as string
}
/**
* Check bitcoin address is valid
* @param testnet testnet or mainnet version of address
* @param address bitcoin address
* @returns true || false
*/
export const isValidAddress = (address: string, network: Network): boolean => {
try {
asdressUtils.toOutputScript(address, network)
return true
} catch (error) {
return false
}
}
/**
* Sign bitcoin tx offline
* @param testnet testnet or mainnet version of address
* @param outputs transaction outputs
* @param privateKey sender private key
* @param toAddress receiver
* @param valueInBtc valut in btc
* @returns rawTx
*/
export const signTxOffline = (outputs: UTXO[], privateKey: string, toAddress: string, value: number, network: Network, changeAddress?: string): string => {
const utxos = outputs.map(x => {
return new Transaction.UnspentOutput({
txId: x.txHash,
outputIndex: x.index,
script: x.script,
satoshis: x.value
})
})
const tx = new Transaction()
.from(utxos)
.to(toAddress, value)
.change(changeAddress || generateAddressFromPrivatekey(privateKey, network))
.sign(privateKey)
tx.verify()
return tx.serialize()
}