Skip to content

Commit

Permalink
BTC testnet/mainnet test pass (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
iower committed May 31, 2021
1 parent 643009b commit 8dba8ea
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 218 deletions.
26 changes: 14 additions & 12 deletions src/crypto/bip44.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
const bip44 = {
createDerivePath(network) {
/*
In fact, not every testnet of coins has an index of 1
Therefore, specify the testnet coin index in the settings
*/
type Path = string

const { coinIndex } = network.settings.bip44
const addressIndex = 0
const createDerivePath = ({ coinIndex, addressIndex }: {
coinIndex: number,
addressIndex: number
}): Path => {
/*
In fact, not every testnet of coins has an index of 1
Therefore, specify the testnet coin index in the settings
*/

const path = `m/44'/${coinIndex}'/0'/0/${addressIndex}`
return path
}
const path = `m/44'/${coinIndex}'/0'/0/${addressIndex}`
return path
}

export default bip44
export default {
createDerivePath
}
24 changes: 13 additions & 11 deletions src/crypto/coins/BTC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as bip39 from 'bip39'
import bitcore from 'bitcore-lib'

import bip44 from '../bip44'
import { ICoin, ENetworkType } from '../index'
import { ICoin, ENetworkType } from '../types'

const netNames = {
mainnet: 'mainnet',
Expand Down Expand Up @@ -57,9 +57,8 @@ const BTC: ICoin = {
}
}
},
profileFromMnemonic({ mnemonic, netName, index }) {
const network = BTC.networks[netName]
const { settings } = network
profileFromMnemonic({ mnemonic, network, addressIndex }) {
const { settings } = BTC.networks[network]

// todo: move?
const seed = bip39.mnemonicToSeedSync(mnemonic)
Expand All @@ -73,21 +72,24 @@ const BTC: ICoin = {
pubKeyHash: settings.base58prefix.pubKeyHash,
scriptHash: settings.base58prefix.scriptHash
})
const derivePath = bip44.createDerivePath(network)
const derivePath = bip44.createDerivePath({
coinIndex: settings.bip44.coinIndex,
addressIndex
})
const child = root.derivePath(derivePath)

let libNetwork

if (netName === netNames.mainnet) {
if (network === netNames.mainnet) {
libNetwork = bitcore.Networks.mainnet
}

if (netName === netNames.testnet) {
if (network === netNames.testnet) {
libNetwork = bitcore.Networks.testnet
}

if (!libNetwork) {
throw new Error(`Unknown network: ${netName}`)
throw new Error(`Unknown network: ${network}`)
}

// eslint-disable-next-line new-cap
Expand All @@ -96,9 +98,9 @@ const BTC: ICoin = {
const address = new bitcore.Address(publicKey, libNetwork)

const account = {
privateKey,
publicKey,
address
privateKey: child.toWIF(),
publicKey: publicKey.toString(),
address: address.toString()
}

return account
Expand Down
12 changes: 9 additions & 3 deletions src/crypto/coins/ETH.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { hdkey } from 'ethereumjs-wallet'
import * as bip39 from 'bip39'
import web3utils from 'web3-utils'

import { ICoin, ENetworkType } from '../index'
import bip44 from '../bip44'
import { ICoin, ENetworkType } from '../types'

const ETH: ICoin = {
symbol: 'ETH',
Expand All @@ -29,11 +30,16 @@ const ETH: ICoin = {
}
}
},
profileFromMnemonic({ mnemonic, netName, index }) {
profileFromMnemonic({ mnemonic, addressIndex }) {
const masterSeed = bip39.mnemonicToSeedSync(mnemonic)
const hdwallet = hdkey.fromMasterSeed(masterSeed)

const wallet = hdwallet.derivePath(`m/44'/60'/0'/0/${index}`).getWallet()
const derivePath = bip44.createDerivePath({
coinIndex: 60,
addressIndex
})

const wallet = hdwallet.derivePath(derivePath).getWallet()
const privateKey = wallet.getPrivateKeyString()
const publicKey = wallet.getPublicKeyString()
/*
Expand Down
18 changes: 10 additions & 8 deletions src/crypto/coins/LTC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as bip39 from 'bip39'
import bitcore from 'bitcore-lib'

import bip44 from '../bip44'
import { ICoin, ENetworkType } from '../index'
import { ICoin, ENetworkType } from '../types'

const netNames = {
mainnet: 'mainnet',
Expand Down Expand Up @@ -60,26 +60,28 @@ const LTC: ICoin = {
}
}
},
profileFromMnemonic({ mnemonic, netName, index }) {
const network = LTC.networks[netName]
const { settings } = network
profileFromMnemonic({ mnemonic, network, addressIndex }) {
const { settings } = LTC.networks[network]

const seed = bip39.mnemonicToSeedSync(mnemonic)
const root = bip32.fromSeed(seed /* , network.bip32settings */)
const derivePath = bip44.createDerivePath(network)
const derivePath = bip44.createDerivePath({
coinIndex: settings.bip44.coinIndex,
addressIndex
})
const child = root.derivePath(derivePath)

let libNetworkName

if (netName === netNames.mainnet) {
if (network === netNames.mainnet) {
libNetworkName = 'litecoin-mainnet'
}
if (netName === netNames.testnet) {
if (network === netNames.testnet) {
libNetworkName = 'litecoin-testnet'
}

if (!libNetworkName) {
throw new Error(`Unknown network: ${netName}`)
throw new Error(`Unknown network: ${network}`)
}

bitcore.Networks.add({
Expand Down
83 changes: 21 additions & 62 deletions src/crypto/index.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,25 @@
/*
seed + password + HD Path => private key
private key => public key
public key => public address
*/

type TMnemonic = string
type TPrivateKey = string
type TPublicKey = string
type TAddress = string

type TNetworkName = string

type TProfile = {
privateKey: TPrivateKey
publicKey: TPublicKey
address: TAddress
}

export enum ENetworkType {
Mainnet = 'Mainnet',
Testnet = 'Testnet'
}

export enum EPreset {
BIP44 = 'BIP44',
electrum = 'electrum'
}

export interface IAddProfileParams {
mnemonic?: TMnemonic
}

export interface ICreateAddressesParams {
coin: 'BTC' | 'LTC' | 'ETH'
preset: EPreset
}

export interface INetwork {
type: ENetworkType
settings: {
port: number
magic: number
messagePrefix: string
base58prefix: {
pubKeyHash: number
scriptHash: number
privateKeyWIF: number
publicKeyBIP32: number
privateKeyBIP32: number
}
bip44: {
coinIndex: number
}
import coins from './coins'
import { TProfile } from './types'

/* interface IProfileFromMnemonicParams {
typeof coins.BTC.profileFromMnemonic ||
typeof coins.LTC.profileFromMnemonic
} */

const profileFromMnemonic: (params) => TProfile = params => {
// todo: improve types - unreliable
if (params.coin === 'BTC') {
return coins.BTC.profileFromMnemonic(params)
}
if (params.coin === 'LTC') {
return coins.LTC.profileFromMnemonic(params)
}
if (params.coin === 'ETH') {
return coins.ETH.profileFromMnemonic(params)
}
throw new Error(`Unknown coin "${params.coin}"`)
}

export interface ICoin {
symbol: string
name: string
precision: number
networks: {
[key: string]: INetwork
}
profileFromMnemonic: ({ mnemonic: TMnemonic, netName: TNetworkName, index: number }) => TProfile
export default {
profileFromMnemonic
}
66 changes: 66 additions & 0 deletions src/crypto/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
seed + password + HD Path => private key
private key => public key
public key => public address
*/

export type TMnemonic = string
export type TPrivateKey = string
export type TPublicKey = string
export type TAddress = string

export type TNetworkName = string

export type TProfile = {
privateKey: TPrivateKey
publicKey: TPublicKey
address: TAddress
}

export enum ENetworkType {
Mainnet = 'Mainnet',
Testnet = 'Testnet'
}

export enum EPreset {
BIP44 = 'BIP44',
electrum = 'electrum'
}

export interface IAddProfileParams {
mnemonic?: TMnemonic
}

export interface ICreateAddressesParams {
coin: 'BTC' | 'LTC' | 'ETH'
preset: EPreset
}

export interface INetwork {
type: ENetworkType
settings: {
port: number
magic: number
messagePrefix: string
base58prefix: {
pubKeyHash: number
scriptHash: number
privateKeyWIF: number
publicKeyBIP32: number
privateKeyBIP32: number
}
bip44: {
coinIndex: number
}
}
}

export interface ICoin {
symbol: string
name: string
precision: number
networks: {
[key: string]: INetwork
}
profileFromMnemonic: ({ mnemonic: TMnemonic, network: TNetworkName, addressIndex: number }) => TProfile
}
Loading

0 comments on commit 8dba8ea

Please sign in to comment.