UNPKG

@ravenrebels/ravencoin-key

Version:

Generate Ravencoin addresses from mnemonic code. BIP32, BIP39, BIP44

173 lines (151 loc) 4.7 kB
//Gives us meta data about coins/chains import { chains } from "@hyperbitjs/chains"; //bip39 from mnemonic to seed import * as bip39 from "bip39"; const CoinKey = require("coinkey"); //From seed to key //const HDKey = require("hdkey"); import HDKey from "hdkey"; import { IAddressObject } from "./types"; //Could not declare Network as enum, something wrong with parcel bundler export type Network = "rvn" | "rvn-test" | "evr" | "evr-test"; function getNetwork(name: Network) { const c = name.toLowerCase(); //Just to be sure const map = { rvn: chains.rvn.mainnet.versions, "rvn-test": chains.rvn.testnet?.versions, evr: chains.evr.mainnet.versions, "evr-test": chains.evr.testnet?.versions, }; const network = map[c]; if (!network) { throw new Error("network must be of value " + Object.keys(map).toString()); } return network; } /** * * @param network * @returns the coin type for the network (blockchain), for example Ravencoin has coin type 175 */ export function getCoinType(network: Network) { const chain = getNetwork(network); return chain.bip44; } /** * @param network - should have value "rvn", "rvn-test", "evr" or "evr-test" * @param mnemonic - your mnemonic * @param account - accounts in BIP44 starts from 0, 0 is the default account * @param position - starts from 0 */ export function getAddressPair( network: Network, mnemonic: string, account: number, position: number ) { const hdKey = getHDKey(network, mnemonic); const coin_type = getCoinType(network); //https://github.com/satoshilabs/slips/blob/master/slip-0044.md //Syntax of BIP44 //m / purpose' / coin_type' / account' / change / address_index const externalPath = `m/44'/${coin_type}'/${account}'/0/${position}`; const externalAddress = getAddressByPath(network, hdKey, externalPath); //change address const internalPath = `m/44'/${coin_type}'/${account}'/1/${position}`; const internalAddress = getAddressByPath(network, hdKey, internalPath); return { internal: internalAddress, external: externalAddress, position, }; } export function getHDKey(network: Network, mnemonic: string): any { const chain = getNetwork(network); const seed = bip39.mnemonicToSeedSync(mnemonic).toString("hex"); //From the seed, get a hdKey, can we use CoinKey instead? const hdKey = HDKey.fromMasterSeed(Buffer.from(seed, "hex"), chain.bip32); return hdKey; } export function getAddressByPath( network: Network, hdKey: any, path: string ): IAddressObject { const chain = getNetwork(network); const derived = hdKey.derive(path); var ck2 = new CoinKey(derived.privateKey, chain); return { address: ck2.publicAddress, path: path, privateKey: ck2.privateKey.toString("hex"), WIF: ck2.privateWif, }; } export function generateMnemonic() { return bip39.generateMnemonic(); } export function isMnemonicValid(mnemonic: string) { //Check all languages const wordlists = Object.values(bip39.wordlists); //If mnemonic is valid in any language, return true, otherwise false for (const wordlist of wordlists) { const v = bip39.validateMnemonic(mnemonic, wordlist); if (v === true) { return true; } } return false; } /** * * @param privateKeyWIF * @param network should be "rvn" or "rvn-test" * @returns object {address, privateKey (hex), WIF} */ export function getAddressByWIF(network: Network, privateKeyWIF: string) { const coinKey = CoinKey.fromWif(privateKeyWIF); coinKey.versions = getNetwork(network); return { address: coinKey.publicAddress, privateKey: coinKey.privateKey.toString("hex"), WIF: coinKey.privateWif, }; } export const entropyToMnemonic = bip39.entropyToMnemonic; export function generateAddressObject( network: Network = "rvn" ): IAddressObject { const mnemonic = generateMnemonic(); const account = 0; const position = 0; const addressPair = getAddressPair(network, mnemonic, account, position); const addressObject = addressPair.external; const result = { ...addressObject, mnemonic, network, }; return result; } /** * Generates a random Address Object * * @deprecated use generateAddressObject * @param network * @returns */ export function generateAddress(network: Network = "rvn") { return generateAddressObject(network); } export default { entropyToMnemonic, generateAddress, generateMnemonic, getAddressByPath, getAddressByWIF, getAddressPair, getCoinType, getHDKey, isMnemonicValid, };