Skip to content
This repository has been archived by the owner on Jan 25, 2024. It is now read-only.

Commit

Permalink
src/coins.js: add getMainnet/getTestnet
Browse files Browse the repository at this point in the history
These methods are useful when grouping tests
  • Loading branch information
OttoAllmendinger committed Jan 8, 2020
1 parent 4827e8a commit 8ddc032
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 7 deletions.
112 changes: 105 additions & 7 deletions src/coins.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,151 @@ const typeforce = require('typeforce')

const networks = require('./networks')

/**
* @param network
* @returns {string} the name of the network. Returns undefined if network is not a value
* of `networks`
*/
function getNetworkName (network) {
return Object.keys(networks).find(n => networks[n] === network)
}

/**
* @param network
* @returns {Object} the mainnet corresponding to a testnet
*/
function getMainnet (network) {
switch (network) {
case networks.bitcoin:
case networks.testnet:
return networks.bitcoin

case networks.bitcoincash:
case networks.bitcoincashTestnet:
return networks.bitcoincash

case networks.bitcoingold:
// FIXME(https://github.com/BitGo/bitgo-utxo-lib/issues/50): define bitcoingoldTest
return networks.bitcoingold

case networks.bitcoinsv:
case networks.bitcoinsvTestnet:
return networks.bitcoinsv

case networks.dash:
case networks.dashTest:
return networks.dash

case networks.litecoin:
case networks.litecoinTest:
return networks.litecoin

case networks.zcash:
case networks.zcashTest:
return networks.zcash
}
throw new TypeError(`invalid network`)
}

/**
* @param network
* @returns {boolean} true iff network is a mainnet
*/
function isMainnet (network) {
return getMainnet(network) === network
}

/**
* @param network
* @returns {boolean} true iff network is a testnet
*/
function isTestnet (network) {
return getMainnet(network) !== network
}

const networksArray = Object.keys(networks).map(name => networks[name])
const mainnets = networksArray.filter(isMainnet)
const testnets = networksArray.filter(isTestnet)
const mainnetTestnetPairs = new Map(
mainnets.map(m => [m, testnets.filter(t => getMainnet(t) === m)])
)

/**
* @param network
* @returns {Object|undefined} - The testnet corresponding to a mainnet.
* Returns undefined if a network has no testnet.
*/
function getTestnet (network) {
if (isTestnet(network)) {
return network
}
const testnets = mainnetTestnetPairs.get(network)
if (testnets === undefined) {
throw new Error(`invalid argument`)
}
if (testnets.length === 0) {
return
}
if (testnets.length === 1) {
return testnets[0]
}
throw new Error(`more than one testnet for ${getNetworkName(network)}`)
}

/**
* @param network
* @returns {boolean} true iff network bitcoin or testnet
*/
function isBitcoin (network) {
return typeforce.value(networks.bitcoin.coin)(network.coin)
return getMainnet(network) === networks.bitcoin
}

/**
* @param network
* @returns {boolean} true iff network is bitcoincash or bitcoincashTestnet
*/
function isBitcoinCash (network) {
return typeforce.value(networks.bitcoincash.coin)(network.coin)
return getMainnet(network) === networks.bitcoincash
}

/**
* @param network
* @returns {boolean} true iff network is bitcoingold
*/
function isBitcoinGold (network) {
return typeforce.value(networks.bitcoingold.coin)(network.coin)
return getMainnet(network) === networks.bitcoingold
}

/**
* @param network
* @returns {boolean} true iff network is bitcoinsv or bitcoinsvTestnet
*/
function isBitcoinSV (network) {
return typeforce.value(networks.bitcoinsv.coin)(network.coin)
return getMainnet(network) === networks.bitcoinsv
}

/**
* @param network
* @returns {boolean} true iff network is dash or dashTest
*/
function isDash (network) {
return typeforce.value(networks.dash.coin)(network.coin)
return getMainnet(network) === networks.dash
}

/**
* @param network
* @returns {boolean} true iff network is litecoin or litecoinTest
*/
function isLitecoin (network) {
return typeforce.value(networks.litecoin.coin)(network.coin)
return getMainnet(network) === networks.litecoin
}

/**
* @param network
* @returns {boolean} true iff network is zcash or zcashTest
*/
function isZcash (network) {
return typeforce.value(networks.zcash.coin)(network.coin)
return getMainnet(network) === networks.zcash
}

/**
Expand All @@ -78,6 +173,8 @@ module.exports = {
LTC: networks.litecoin.coin,
ZEC: networks.zcash.coin,

getNetworkName,

getMainnet,
isMainnet,
getTestnet,
Expand All @@ -96,4 +193,5 @@ module.exports = {
* @deprecated: use isValidNetwork
*/
isValidCoin: isValidNetwork

}
2 changes: 2 additions & 0 deletions src/networks.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ module.exports = {
messagePrefix: '\x19Litecoin Signed Message:\n',
bech32: 'ltc',
bip32: {
// FIXME(BG-16466): these are incorrect
public: 0x019da462,
private: 0x019d9cfe
},
Expand All @@ -165,6 +166,7 @@ module.exports = {
messagePrefix: '\x19Litecoin Signed Message:\n',
bech32: 'tltc',
bip32: {
// FIXME(BG-16466): these are incorrect
public: 0x0488b21e,
private: 0x0488ade4
},
Expand Down
39 changes: 39 additions & 0 deletions test/networks.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ describe('networks', function () {
assert(coins.isValidNetwork(network))
})

it('getNetworkName() returns network name', function () {
assert.strictEqual(name, coins.getNetworkName(network))
})

it('has corresponding testnet/mainnet', function () {
if (coins.isMainnet(network)) {
assert.strictEqual(coins.isTestnet(network), false)
assert.strictEqual(coins.getMainnet(network), network)
assert.strictEqual(
typeof coins.getTestnet(network),
(network === networks.bitcoingold) ? 'undefined' : 'object'
)
} else {
assert.strictEqual(coins.isMainnet(network), false)
assert.strictEqual(coins.getTestnet(network), network)
assert.notStrictEqual(coins.getMainnet(network), network)
assert.strictEqual(typeof coins.getMainnet(network), 'object')
}
})

it('has expected properties', function () {
assert.strictEqual(typeof network, 'object')
assert.strictEqual(typeof network.messagePrefix, 'string')
Expand All @@ -80,6 +100,25 @@ describe('networks', function () {
assert.strictEqual(typeof network.scriptHash, 'number')
assert.strictEqual(typeof network.wif, 'number')
assert.strictEqual(typeof network.coin, 'string')

// FIXME(BG-16466): litecoin should not be a special case here -- all forks have the same bip32 values
const isLitecoin = coins.getMainnet(network) === networks.litecoin

if (coins.isMainnet(network)) {
assert.strictEqual(
(network.bip32.public === networks.bitcoin.bip32.public), !isLitecoin
)
assert.strictEqual(
(network.bip32.private === networks.bitcoin.bip32.private), !isLitecoin
)
} else {
assert.strictEqual(
(network.bip32.public === networks.testnet.bip32.public), !isLitecoin
)
assert.strictEqual(
(network.bip32.private === networks.testnet.bip32.private), !isLitecoin
)
}
})

for (const otherName in networks) {
Expand Down

0 comments on commit 8ddc032

Please sign in to comment.