Files
bch-js/test/unit/bitcoin-cash.js

325 lines
11 KiB
JavaScript

// Public npm libraries
import assert from 'assert'
// Mocks
import { createRequire } from 'module'
// Unit under test (uut)
import BCHJS from '../../src/bch-js.js'
const require = createRequire(import.meta.url)
const fixtures = require('./fixtures/bitcoincash.json')
// const bchjs = new BCHJS()
let bchjs
// TODO
// 1. generate testnet p2sh
// 2. generate cashaddr mainnet p2sh
// 3. generate cashaddr testnet p2sh
// 4. create bchjs fromBase58 method
// * confirm xpub cannot generate WIF
// * confirm xpriv can generate WIF
// 5. create fromXPriv method w/ tests and docs
// 1. mainnet
// * confirm xpriv generates address
// * confirm xpriv generates WIF
// 2. testnet
// * confirm xpriv generates address
// * confirm xpriv generates WIF
// 6. More error test cases.
describe('#BitcoinCash', () => {
beforeEach(() => {
bchjs = new BCHJS()
})
describe('price conversion', () => {
it('should exercise toBitcoinCash', () => {
fixtures.conversion.toBCH.satoshis.forEach(satoshi => {
it(`should convert ${satoshi[0]} Satoshis to ${satoshi[1]} $BCH`, () => {
assert.equal(bchjs.BitcoinCash.toBitcoinCash(satoshi[0]), satoshi[1])
})
})
fixtures.conversion.toBCH.strings.forEach(satoshi => {
it(`should convert "${satoshi[0]}" Satoshis as a string to ${satoshi[1]} $BCH`, () => {
assert.equal(bchjs.BitcoinCash.toBitcoinCash(satoshi[0]), satoshi[1])
})
})
fixtures.conversion.toBCH.not.forEach(bch => {
it(`converts ${bch[0]} to Bitcoin Cash, not to ${bch[1]} Satoshi`, () => {
assert.notEqual(bchjs.BitcoinCash.toBitcoinCash(bch[0]), bch[1])
})
})
fixtures.conversion.toBCH.rounding.forEach(satoshi => {
it(`rounding ${satoshi[0]} to ${satoshi[1]} $BCH`, () => {
assert.equal(bchjs.BitcoinCash.toBitcoinCash(satoshi[0]), satoshi[1])
})
})
})
it('should exercise toSatoshi', () => {
fixtures.conversion.toSatoshi.bch.forEach(bch => {
it(`should convert ${bch[0]} $BCH to ${bch[1]} Satoshis`, () => {
assert.equal(bchjs.BitcoinCash.toSatoshi(bch[0]), bch[1])
})
})
fixtures.conversion.toSatoshi.strings.forEach(bch => {
it(`should convert "${bch[0]}" $BCH as a string to ${bch[1]} Satoshis`, () => {
assert.equal(bchjs.BitcoinCash.toSatoshi(bch[0]), bch[1])
})
})
fixtures.conversion.toSatoshi.not.forEach(satoshi => {
it(`converts ${satoshi[0]} to Satoshi, not to ${satoshi[1]} Bitcoin Cash`, () => {
assert.notEqual(bchjs.BitcoinCash.toSatoshi(satoshi[0]), satoshi[1])
})
})
fixtures.conversion.toSatoshi.rounding.forEach(bch => {
it(`rounding ${bch[0]} to ${bch[1]} Satoshi`, () => {
assert.equal(bchjs.BitcoinCash.toSatoshi(bch[0]), bch[1])
})
})
})
it('should exercise satsToBits', () => {
fixtures.conversion.satsToBits.bch.forEach(bch => {
it(`should convert ${bch[0]} BCH to ${bch[1]} bits`, () => {
assert.equal(
bchjs.BitcoinCash.satsToBits(bchjs.BitcoinCash.toSatoshi(bch[0])),
bch[1]
)
})
})
fixtures.conversion.satsToBits.strings.forEach(bch => {
it(`should convert "${bch[0]}" BCH as a string to ${bch[1]} bits`, () => {
assert.equal(
bchjs.BitcoinCash.satsToBits(bchjs.BitcoinCash.toSatoshi(bch[0])),
bch[1]
)
})
})
})
//
// describe('#satsFromBits', () => {
// fixtures.conversion.satsFromBits.bch.forEach((bch) => {
// it(`should convert ${bch[1]} bits to ${bch[0]} satoshis`, () => {
// assert.equal(bchjs.BitcoinCash.satsFromBits(bch[1]), bch[0]);
// });
// });
//
// fixtures.conversion.satsFromBits.strings.forEach((bch) => {
// it(`should convert "${bch[1]}" bits as a string to ${bch[0]} satoshis`, () => {
// assert.equal(bchjs.BitcoinCash.satsFromBits(bch[1]), bch[0]);
// });
// });
// });
})
describe('sign and verify messages', () => {
it('should exercise signMessageWithPrivKey', () => {
fixtures.signatures.sign.forEach(sign => {
it(`should sign a message w/ ${sign.network} ${sign.privateKeyWIF}`, () => {
const privateKeyWIF = sign.privateKeyWIF
const message = sign.message
const signature = bchjs.BitcoinCash.signMessageWithPrivKey(
privateKeyWIF,
message
)
assert.equal(signature, sign.signature)
})
})
})
it('shoudl exercise verifyMessage', () => {
fixtures.signatures.verify.forEach(sign => {
it(`should verify a valid signed message from ${sign.network} cashaddr address ${sign.address}`, () => {
assert.equal(
bchjs.BitcoinCash.verifyMessage(
sign.address,
sign.signature,
sign.message
),
true
)
})
})
it('should verify legacy addresses', () => {
fixtures.signatures.verify.forEach(sign => {
const legacyAddress = bchjs.Address.toLegacyAddress(sign.address)
it(`should verify a valid signed message from ${sign.network} legacy address ${legacyAddress}`, () => {
assert.equal(
bchjs.BitcoinCash.verifyMessage(
legacyAddress,
sign.signature,
sign.message
),
true
)
})
})
})
fixtures.signatures.verify.forEach(sign => {
// const legacyAddress = bchjs.Address.toLegacyAddress(sign.address)
it(`should not verify an invalid signed message from ${sign.network} cashaddr address ${sign.address}`, () => {
assert.equal(
bchjs.BitcoinCash.verifyMessage(
sign.address,
sign.signature,
'nope'
),
false
)
})
})
})
})
describe('encode and decode to base58Check', () => {
describe('#encodeBase58Check', () => {
fixtures.encodeBase58Check.forEach((base58Check, i) => {
it(`encode ${base58Check.hex} as base58Check ${base58Check.base58Check}`, () => {
assert.equal(
bchjs.BitcoinCash.encodeBase58Check(base58Check.hex),
base58Check.base58Check
)
})
})
})
describe('#decodeBase58Check', () => {
fixtures.encodeBase58Check.forEach((base58Check, i) => {
it(`decode ${base58Check.base58Check} as ${base58Check.hex}`, () => {
assert.equal(
bchjs.BitcoinCash.decodeBase58Check(base58Check.base58Check),
base58Check.hex
)
})
})
})
})
describe('encode and decode BIP21 urls', () => {
describe('#encodeBIP21', () => {
fixtures.bip21.valid.forEach((bip21, i) => {
it(`encode ${bip21.address} as url`, () => {
const url = bchjs.BitcoinCash.encodeBIP21(
bip21.address,
bip21.options
)
assert.equal(url, bip21.url)
})
})
fixtures.bip21.valid_regtest.forEach((bip21, i) => {
it(`encode ${bip21.address} as url`, () => {
const url = bchjs.BitcoinCash.encodeBIP21(
bip21.address,
bip21.options,
true
)
assert.equal(url, bip21.url)
})
})
})
describe('#decodeBIP21', () => {
fixtures.bip21.valid.forEach((bip21, i) => {
it(`decodes ${bip21.url}`, () => {
const decoded = bchjs.BitcoinCash.decodeBIP21(bip21.url)
assert.equal(decoded.options.amount, bip21.options.amount)
assert.equal(decoded.options.label, bip21.options.label)
assert.equal(
bchjs.Address.toCashAddress(decoded.address),
bchjs.Address.toCashAddress(bip21.address)
)
})
})
// fixtures.bip21.valid_regtest.forEach((bip21, i) => {
// it(`decodes ${bip21.url}`, () => {
// const decoded = bchjs.BitcoinCash.decodeBIP21(bip21.url)
// assert.equal(decoded.options.amount, bip21.options.amount)
// assert.equal(decoded.options.label, bip21.options.label)
// assert.equal(
// bchjs.Address.toCashAddress(decoded.address, true, true),
// bchjs.Address.toCashAddress(bip21.address, true, true)
// )
// })
// })
})
})
describe('#getByteCount', () => {
fixtures.getByteCount.forEach(fixture => {
it('get byte count', () => {
const byteCount = bchjs.BitcoinCash.getByteCount(
fixture.inputs,
fixture.outputs
)
assert.equal(byteCount, fixture.byteCount)
})
})
})
describe('#bip38', function () {
// Increase timeout for BIP38 tests as they use CPU-intensive scrypt operations
// Each encrypt/decrypt operation takes ~5-6 seconds in Node.js v22
this.timeout(60000)
describe('#encryptBIP38', () => {
fixtures.bip38.encrypt.mainnet.forEach(fixture => {
it(`BIP 38 encrypt wif ${fixture.wif} with password ${fixture.password} on mainnet`, function () {
this.timeout(60000)
const encryptedKey = bchjs.BitcoinCash.encryptBIP38(
fixture.wif,
fixture.password
)
assert.equal(encryptedKey, fixture.encryptedKey)
})
})
// fixtures.bip38.encrypt.testnet.forEach(fixture => {
// it(`BIP 38 encrypt wif ${fixture.wif} with password ${fixture.password} on testnet`, function () {
// this.timeout(60000)
// const encryptedKey = bchjs.BitcoinCash.encryptBIP38(
// fixture.wif,
// fixture.password
// )
// assert.equal(encryptedKey, fixture.encryptedKey)
// })
// })
})
describe('#decryptBIP38', () => {
fixtures.bip38.decrypt.mainnet.forEach(fixture => {
it(`BIP 38 decrypt encrypted key ${fixture.encryptedKey} on mainnet`, function () {
this.timeout(60000)
const wif = bchjs.BitcoinCash.decryptBIP38(
fixture.encryptedKey,
fixture.password,
'mainnet'
)
assert.equal(wif, fixture.wif)
})
})
// fixtures.bip38.decrypt.testnet.forEach(fixture => {
// it(`BIP 38 decrypt encrypted key ${fixture.encryptedKey} on testnet`, function () {
// this.timeout(60000)
// const wif = bchjs.BitcoinCash.decryptBIP38(
// fixture.encryptedKey,
// fixture.password,
// 'testnet'
// )
// assert.equal(wif, fixture.wif)
// })
// })
})
})
})