mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-21 16:51:59 -07:00
fix(address unit tests): Fixed to prevent network call
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@
|
||||
],
|
||||
"main": "src/bch-js",
|
||||
"scripts": {
|
||||
"test": "nyc mocha --timeout 30000 test/unit/",
|
||||
"test": "nyc mocha --trace-warnings --unhandled-rejections=strict --timeout 30000 test/unit/",
|
||||
"test:integration": "bash test/integration/test-bchn-integration.sh",
|
||||
"test:integration:bchn": "bash test/integration/test-bchn-integration.sh",
|
||||
"test:integration:abc": "RESTURL=https://abc.fullstack.cash/v4/ IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/",
|
||||
|
||||
+785
-751
File diff suppressed because it is too large
Load Diff
@@ -1,314 +0,0 @@
|
||||
const fixtures = require("./fixtures/bitcoincash.json")
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new 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", () => {
|
||||
describe("price conversion", () => {
|
||||
describe("#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])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#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])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#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", () => {
|
||||
describe("#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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#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
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
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", () => {
|
||||
describe("#encryptBIP38", () => {
|
||||
fixtures.bip38.encrypt.mainnet.forEach(fixture => {
|
||||
it(`BIP 38 encrypt wif ${fixture.wif} with password ${fixture.password} on mainnet`, () => {
|
||||
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`, () => {
|
||||
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`, () => {
|
||||
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`, () => {
|
||||
const wif = bchjs.BitcoinCash.decryptBIP38(
|
||||
fixture.encryptedKey,
|
||||
fixture.password,
|
||||
"testnet"
|
||||
)
|
||||
assert.equal(wif, fixture.wif)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,275 +0,0 @@
|
||||
const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const axios = require("axios")
|
||||
const sinon = require("sinon")
|
||||
|
||||
const mockData = require("./fixtures/blockbook-mock")
|
||||
|
||||
describe(`#Blockbook`, () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe(`#Balance`, () => {
|
||||
it(`should GET balance for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.balance })
|
||||
|
||||
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
const result = await bchjs.Blockbook.balance(addr)
|
||||
//console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.hasAnyKeys(result, [
|
||||
"page",
|
||||
"totalPages",
|
||||
"itemsOnPage",
|
||||
"address",
|
||||
"balance",
|
||||
"totalReceived",
|
||||
"totalSent",
|
||||
"unconfirmedBalance",
|
||||
"unconfirmedTxs",
|
||||
"txs",
|
||||
"txids"
|
||||
])
|
||||
assert.isArray(result.txids)
|
||||
})
|
||||
|
||||
it(`should POST request balances for an array of addresses`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(axios, "post")
|
||||
.resolves({ data: [mockData.balance, mockData.balance] })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
const result = await bchjs.Blockbook.balance(addr)
|
||||
//console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.hasAnyKeys(result[0], [
|
||||
"page",
|
||||
"totalPages",
|
||||
"itemsOnPage",
|
||||
"address",
|
||||
"balance",
|
||||
"totalReceived",
|
||||
"totalSent",
|
||||
"unconfirmedBalance",
|
||||
"unconfirmedTxs",
|
||||
"txs",
|
||||
"txids"
|
||||
])
|
||||
assert.isArray(result[0].txids)
|
||||
})
|
||||
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(axios, "post")
|
||||
.throws(`Input address must be a string or array of strings`)
|
||||
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Blockbook.balance(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
/*
|
||||
it(`should throw error on array size rate limit`, async () => {
|
||||
try {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").throws(`Array too large`)
|
||||
|
||||
const addr = []
|
||||
for (let i = 0; i < 25; i++)
|
||||
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
|
||||
|
||||
const result = await bchjs.Blockbook.balance(addr)
|
||||
|
||||
console.log(`result: ${util.inspect(result)}`)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
assert.hasAnyKeys(err, ["error"])
|
||||
assert.include(err.error, "Array too large")
|
||||
}
|
||||
})
|
||||
*/
|
||||
})
|
||||
|
||||
describe(`#utxo`, () => {
|
||||
it(`should GET utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
const result = await bchjs.Blockbook.utxo(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.hasAnyKeys(result[0], [
|
||||
"txid",
|
||||
"vout",
|
||||
"value",
|
||||
"height",
|
||||
"confirmations"
|
||||
])
|
||||
})
|
||||
|
||||
it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxos })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
const result = await bchjs.Blockbook.utxo(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.isArray(result[0])
|
||||
assert.hasAnyKeys(result[0][0], [
|
||||
"txid",
|
||||
"vout",
|
||||
"value",
|
||||
"height",
|
||||
"confirmations"
|
||||
])
|
||||
})
|
||||
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(axios, "post")
|
||||
.throws(`Input address must be a string or array of strings`)
|
||||
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Blockbook.utxo(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
/*
|
||||
it(`should throw error on array size rate limit`, async () => {
|
||||
try {
|
||||
const addr = []
|
||||
for (let i = 0; i < 25; i++)
|
||||
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
|
||||
|
||||
const result = await bchjs.Blockbook.utxo(addr)
|
||||
|
||||
console.log(`result: ${util.inspect(result)}`)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
assert.hasAnyKeys(err, ["error"])
|
||||
assert.include(err.error, "Array too large")
|
||||
}
|
||||
})
|
||||
*/
|
||||
})
|
||||
|
||||
describe(`#tx`, () => {
|
||||
it(`should GET tx details for a single txid`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
const result = await bchjs.Blockbook.utxo(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.hasAnyKeys(result[0], [
|
||||
"txid",
|
||||
"vout",
|
||||
"value",
|
||||
"height",
|
||||
"confirmations"
|
||||
])
|
||||
})
|
||||
|
||||
// it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// // Stub the network call.
|
||||
// sandbox.stub(axios, "post").resolves({ data: mockData.utxos })
|
||||
//
|
||||
// const addr = [
|
||||
// "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
// "bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
// ]
|
||||
//
|
||||
// const result = await bchjs.Blockbook.utxo(addr)
|
||||
// //console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
//
|
||||
// assert.isArray(result)
|
||||
// assert.isArray(result[0])
|
||||
// assert.hasAnyKeys(result[0][0], [
|
||||
// "txid",
|
||||
// "vout",
|
||||
// "value",
|
||||
// "height",
|
||||
// "confirmations"
|
||||
// ])
|
||||
// })
|
||||
|
||||
// it(`should throw an error for improper input`, async () => {
|
||||
// try {
|
||||
// // Stub the network call.
|
||||
// sandbox
|
||||
// .stub(axios, "post")
|
||||
// .throws(`Input address must be a string or array of strings`)
|
||||
//
|
||||
// const addr = 12345
|
||||
//
|
||||
// await bchjs.Blockbook.utxo(addr)
|
||||
// assert.equal(true, false, "Unexpected result!")
|
||||
// } catch (err) {
|
||||
// //console.log(`err: `, err)
|
||||
// assert.include(
|
||||
// err.message,
|
||||
// `Input address must be a string or array of strings`
|
||||
// )
|
||||
// }
|
||||
// })
|
||||
|
||||
/*
|
||||
it(`should throw error on array size rate limit`, async () => {
|
||||
try {
|
||||
const addr = []
|
||||
for (let i = 0; i < 25; i++)
|
||||
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
|
||||
|
||||
const result = await bchjs.Blockbook.utxo(addr)
|
||||
|
||||
console.log(`result: ${util.inspect(result)}`)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
assert.hasAnyKeys(err, ["error"])
|
||||
assert.include(err.error, "Array too large")
|
||||
}
|
||||
})
|
||||
*/
|
||||
})
|
||||
})
|
||||
@@ -1,494 +0,0 @@
|
||||
const assert = require("assert")
|
||||
const assert2 = require("chai").assert
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
const mockData = require("./fixtures/blockchain-mock")
|
||||
|
||||
describe("#Blockchain", () => {
|
||||
describe("#getBestBlockHash", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get best block hash", done => {
|
||||
const resolved = new Promise(r =>
|
||||
r({
|
||||
data:
|
||||
"0000000000000000005f1f550d3d8b142b684277016ebd00fa29c668606ae52d"
|
||||
})
|
||||
)
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getBestBlockHash()
|
||||
.then(result => {
|
||||
const hash =
|
||||
"0000000000000000005f1f550d3d8b142b684277016ebd00fa29c668606ae52d"
|
||||
assert.equal(hash, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getBlock", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
hash: "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09",
|
||||
confirmations: 526807,
|
||||
size: 216,
|
||||
height: 1000,
|
||||
version: 1,
|
||||
versionHex: "00000001",
|
||||
merkleroot:
|
||||
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
|
||||
tx: ["fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33"],
|
||||
time: 1232346882,
|
||||
mediantime: 1232344831,
|
||||
nonce: 2595206198,
|
||||
bits: "1d00ffff",
|
||||
difficulty: 1,
|
||||
chainwork:
|
||||
"000000000000000000000000000000000000000000000000000003e903e903e9",
|
||||
previousblockhash:
|
||||
"0000000008e647742775a230787d66fdf92c46a48c896bfbc85cdc8acc67e87d",
|
||||
nextblockhash:
|
||||
"00000000a2887344f8db859e372e7e4bc26b23b9de340f725afbf2edb265b4c6"
|
||||
}
|
||||
|
||||
it("should get block by hash", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getBlock(
|
||||
"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getBlockchainInfo", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
chain: "main",
|
||||
blocks: 527810,
|
||||
headers: 527810,
|
||||
bestblockhash:
|
||||
"000000000000000001d127592d091d4c45062504663c9acab27a1b16c028e3c0",
|
||||
difficulty: 576023394804.6666,
|
||||
mediantime: 1524878499,
|
||||
verificationprogress: 0.9999990106793685,
|
||||
chainwork:
|
||||
"00000000000000000000000000000000000000000096da5b040913fa09249b4e",
|
||||
pruned: false,
|
||||
softforks: [
|
||||
{ id: "bip34", version: 2, reject: [Object] },
|
||||
{ id: "bip66", version: 3, reject: [Object] },
|
||||
{ id: "bip65", version: 4, reject: [Object] }
|
||||
],
|
||||
bip9_softforks: {
|
||||
csv: {
|
||||
status: "active",
|
||||
startTime: 1462060800,
|
||||
timeout: 1493596800,
|
||||
since: 419328
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it("should get blockchain info", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getBlockchainInfo()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getBlockCount", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = 527810
|
||||
|
||||
it("should get block count", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getBlockCount()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getBlockHash", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data =
|
||||
"000000000000000001d127592d091d4c45062504663c9acab27a1b16c028e3c0"
|
||||
|
||||
it("should get block hash by height", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getBlockHash(527810)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getBlockHeader", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
hash: "000000000000000001d127592d091d4c45062504663c9acab27a1b16c028e3c0",
|
||||
confirmations: 1,
|
||||
height: 527810,
|
||||
version: 536870912,
|
||||
versionHex: "20000000",
|
||||
merkleroot:
|
||||
"9298432bbebe4638456aa19cb7ef91639da87668a285d88d0ecd6080424d223b",
|
||||
time: 1524881438,
|
||||
mediantime: 1524878499,
|
||||
nonce: 3326843941,
|
||||
bits: "1801e8a5",
|
||||
difficulty: 576023394804.6666,
|
||||
chainwork:
|
||||
"00000000000000000000000000000000000000000096da5b040913fa09249b4e",
|
||||
previousblockhash:
|
||||
"000000000000000000b33251708bc7a7b4540e61880d8c376e8e2db6a19a4789"
|
||||
}
|
||||
|
||||
it("should get block header by hash", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getBlockHeader(
|
||||
"000000000000000001d127592d091d4c45062504663c9acab27a1b16c028e3c0",
|
||||
true
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getDifficulty", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = "577528469277.1339"
|
||||
|
||||
it("should get difficulty", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getDifficulty()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getMempoolAncestors", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = "Transaction not in mempool"
|
||||
|
||||
it("should get mempool ancestors", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getMempoolAncestors(
|
||||
"daf58932cb91619304dd4cbd03c7202e89ad7d6cbd6e2209e5f64ce3b6ed7c88",
|
||||
true
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getMempoolDescendants", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
result: "Transaction not in mempool"
|
||||
}
|
||||
|
||||
it("should get mempool descendants", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getMempoolDescendants(
|
||||
"daf58932cb91619304dd4cbd03c7202e89ad7d6cbd6e2209e5f64ce3b6ed7c88",
|
||||
true
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getMempoolEntry", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
result: "Transaction not in mempool"
|
||||
}
|
||||
|
||||
it("should get mempool entry", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getMempoolEntry(
|
||||
"daf58932cb91619304dd4cbd03c7202e89ad7d6cbd6e2209e5f64ce3b6ed7c88"
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getMempoolInfo", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
result: {
|
||||
size: 317,
|
||||
bytes: 208583,
|
||||
usage: 554944,
|
||||
maxmempool: 300000000,
|
||||
mempoolminfee: 0
|
||||
}
|
||||
}
|
||||
|
||||
it("should get mempool info", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getMempoolInfo()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getRawMempool", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
result: {
|
||||
transactions: [
|
||||
{
|
||||
txid:
|
||||
"ab36d68dd0a618592fe34e4a898e8beeeb4049133547dbb16f9338384084af96",
|
||||
size: 191,
|
||||
fee: 0.00047703,
|
||||
modifiedfee: 0.00047703,
|
||||
time: 1524883317,
|
||||
height: 527811,
|
||||
startingpriority: 5287822727.272727,
|
||||
currentpriority: 5287822727.272727,
|
||||
descendantcount: 1,
|
||||
descendantsize: 191,
|
||||
descendantfees: 47703,
|
||||
ancestorcount: 1,
|
||||
ancestorsize: 191,
|
||||
ancestorfees: 47703,
|
||||
depends: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
it("should get mempool info", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.getRawMempool()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getTxOut", () => {
|
||||
// TODO finish this test
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
// const data = {
|
||||
// result: {}
|
||||
// }
|
||||
|
||||
it("should throw an error for improper txid.", async () => {
|
||||
try {
|
||||
await bchjs.Blockchain.getTxOut("badtxid")
|
||||
} catch (err) {
|
||||
assert2.include(err.message, "txid needs to be a proper transaction ID")
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw an error if no vout value is provided.", async () => {
|
||||
try {
|
||||
await bchjs.Blockchain.getTxOut(
|
||||
"daf58932cb91619304dd4cbd03c7202e89ad7d6cbd6e2209e5f64ce3b6ed7c88"
|
||||
)
|
||||
} catch (err) {
|
||||
assert2.include(err.message, "n must be an integer")
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw an error if include_mempool is not a boolean", async () => {
|
||||
try {
|
||||
await bchjs.Blockchain.getTxOut(
|
||||
"daf58932cb91619304dd4cbd03c7202e89ad7d6cbd6e2209e5f64ce3b6ed7c88",
|
||||
0,
|
||||
"bad value"
|
||||
)
|
||||
} catch (err) {
|
||||
assert2.include(
|
||||
err.message,
|
||||
"include_mempool input must be of type boolean"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should get information on an unspent tx", async () => {
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.txOutUnspent })
|
||||
|
||||
const result = await bchjs.Blockchain.getTxOut(
|
||||
"62a3ea958a463a372bc0caf2c374a7f60be9c624be63a0db8db78f05809df6d8",
|
||||
0,
|
||||
true
|
||||
)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert2.hasAllKeys(result, [
|
||||
"bestblock",
|
||||
"confirmations",
|
||||
"value",
|
||||
"scriptPubKey",
|
||||
"coinbase"
|
||||
])
|
||||
})
|
||||
|
||||
it("should get information on a spent tx", async () => {
|
||||
sandbox.stub(axios, "post").resolves({ data: null })
|
||||
|
||||
const result = await bchjs.Blockchain.getTxOut(
|
||||
"87380e52d151856b23173d6d8a3db01b984c6b50f77ea045a5a1cf4f54497871",
|
||||
0,
|
||||
true
|
||||
)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert2.equal(result, null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#preciousBlock", () => {
|
||||
// TODO finish this test
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = {
|
||||
result: {}
|
||||
}
|
||||
|
||||
it("should get TODO", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.preciousBlock()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#pruneBlockchain", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = "Cannot prune blocks because node is not in prune mode."
|
||||
|
||||
it("should prune blockchain", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "post").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.pruneBlockchain(507)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#verifyChain", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = true
|
||||
|
||||
it("should verify blockchain", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.verifyChain(3, 6)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#verifyTxOutProof", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
const data = "proof must be hexadecimal string (not '')"
|
||||
|
||||
it("should verify utxo proof", done => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Blockchain.verifyTxOutProof("3")
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,64 +0,0 @@
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
describe("#Control", () => {
|
||||
describe("#getNetworkInfo", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get info", done => {
|
||||
const data = {
|
||||
version: 170000,
|
||||
protocolversion: 70015,
|
||||
blocks: 527813,
|
||||
timeoffset: 0,
|
||||
connections: 21,
|
||||
proxy: "",
|
||||
difficulty: 581086703759.5878,
|
||||
testnet: false,
|
||||
paytxfee: 0,
|
||||
relayfee: 0.00001,
|
||||
errors: ""
|
||||
}
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Control.getNetworkInfo()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getMemoryInfo", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get memory info", done => {
|
||||
const data = {
|
||||
locked: {
|
||||
used: 0,
|
||||
free: 65536,
|
||||
total: 65536,
|
||||
locked: 65536,
|
||||
chunks_used: 0,
|
||||
chunks_free: 1
|
||||
}
|
||||
}
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Control.getMemoryInfo()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,100 +0,0 @@
|
||||
const fixtures = require("./fixtures/crypto.json")
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
describe("#Crypto", () => {
|
||||
describe("#sha256", () => {
|
||||
fixtures.sha256.forEach(fixture => {
|
||||
it(`should create SHA256Hash hex encoded ${fixture.hash} from ${fixture.hex}`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const sha256Hash = bchjs.Crypto.sha256(data).toString("hex")
|
||||
assert.equal(sha256Hash, fixture.hash)
|
||||
})
|
||||
|
||||
it(`should create 64 character SHA256Hash hex encoded`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const sha256Hash = bchjs.Crypto.sha256(data).toString("hex")
|
||||
assert.equal(sha256Hash.length, 64)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#ripemd160", () => {
|
||||
fixtures.ripemd160.forEach(fixture => {
|
||||
it(`should create RIPEMD160Hash hex encoded ${fixture.hash} from ${fixture.hex}`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const ripemd160 = bchjs.Crypto.ripemd160(data).toString("hex")
|
||||
assert.equal(ripemd160, fixture.hash)
|
||||
})
|
||||
|
||||
it(`should create 64 character RIPEMD160Hash hex encoded`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const ripemd160 = bchjs.Crypto.ripemd160(data).toString("hex")
|
||||
assert.equal(ripemd160.length, 40)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#hash256", () => {
|
||||
fixtures.hash256.forEach(fixture => {
|
||||
it(`should create double SHA256 Hash hex encoded ${fixture.hash} from ${fixture.hex}`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const hash256 = bchjs.Crypto.hash256(data).toString("hex")
|
||||
assert.equal(hash256, fixture.hash)
|
||||
})
|
||||
|
||||
it(`should create 64 character SHA256 Hash hex encoded`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const hash256 = bchjs.Crypto.hash256(data).toString("hex")
|
||||
assert.equal(hash256.length, 64)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#hash160", () => {
|
||||
fixtures.hash160.forEach(fixture => {
|
||||
it(`should create RIPEMD160(SHA256()) hex encoded ${fixture.hash} from ${fixture.hex}`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const hash160 = bchjs.Crypto.hash160(data).toString("hex")
|
||||
assert.equal(hash160, fixture.hash)
|
||||
})
|
||||
|
||||
it(`should create 64 character SHA256Hash hex encoded`, () => {
|
||||
const data = Buffer.from(fixture.hex, "hex")
|
||||
const hash160 = bchjs.Crypto.hash160(data).toString("hex")
|
||||
assert.equal(hash160.length, 40)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#randomBytes", () => {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
it("should return 16 bytes of entropy hex encoded", () => {
|
||||
const entropy = bchjs.Crypto.randomBytes(16)
|
||||
assert.equal(Buffer.byteLength(entropy), 16)
|
||||
})
|
||||
|
||||
it("should return 20 bytes of entropy hex encoded", () => {
|
||||
const entropy = bchjs.Crypto.randomBytes(20)
|
||||
assert.equal(Buffer.byteLength(entropy), 20)
|
||||
})
|
||||
|
||||
it("should return 24 bytes of entropy hex encoded", () => {
|
||||
const entropy = bchjs.Crypto.randomBytes(24)
|
||||
assert.equal(Buffer.byteLength(entropy), 24)
|
||||
})
|
||||
|
||||
it("should return 28 bytes of entropy hex encoded", () => {
|
||||
const entropy = bchjs.Crypto.randomBytes(28)
|
||||
assert.equal(Buffer.byteLength(entropy), 28)
|
||||
})
|
||||
|
||||
it("should return 32 bytes of entropy hex encoded", () => {
|
||||
const entropy = bchjs.Crypto.randomBytes(32)
|
||||
assert.equal(Buffer.byteLength(entropy), 32)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,146 +0,0 @@
|
||||
const assert = require("assert")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
const fixtures = require("./fixtures/ecpair.json")
|
||||
|
||||
describe("#ECPair", () => {
|
||||
describe("#fromWIF", () => {
|
||||
fixtures.fromWIF.forEach(fixture => {
|
||||
it(`should create ECPair from WIF ${fixture.privateKeyWIF}`, () => {
|
||||
const ecpair = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
assert.equal(typeof ecpair, "object")
|
||||
})
|
||||
|
||||
it(`should get ${fixture.legacy} legacy address`, () => {
|
||||
const legacy = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(legacy), fixture.legacy)
|
||||
})
|
||||
|
||||
it(`should get ${fixture.cashAddr} cash address`, () => {
|
||||
const cashAddr = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
assert.equal(bchjs.HDNode.toCashAddress(cashAddr), fixture.cashAddr)
|
||||
})
|
||||
|
||||
it(`should get ${fixture.regtestAddr} cash address`, () => {
|
||||
const cashAddr = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(cashAddr, true),
|
||||
fixture.regtestAddr
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toWIF", () => {
|
||||
fixtures.toWIF.forEach(fixture => {
|
||||
it(`should get WIF ${fixture.privateKeyWIF} from ECPair`, () => {
|
||||
const ecpair = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
const wif = bchjs.ECPair.toWIF(ecpair)
|
||||
assert.equal(wif, fixture.privateKeyWIF)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#fromPublicKey", () => {
|
||||
fixtures.fromPublicKey.forEach(fixture => {
|
||||
it(`should create ECPair from public key buffer`, () => {
|
||||
const ecpair = bchjs.ECPair.fromPublicKey(
|
||||
Buffer.from(fixture.pubkeyHex, "hex")
|
||||
)
|
||||
assert.equal(typeof ecpair, "object")
|
||||
})
|
||||
|
||||
it(`should get ${fixture.legacy} legacy address`, () => {
|
||||
const ecpair = bchjs.ECPair.fromPublicKey(
|
||||
Buffer.from(fixture.pubkeyHex, "hex")
|
||||
)
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(ecpair), fixture.legacy)
|
||||
})
|
||||
|
||||
it(`should get ${fixture.cashAddr} cash address`, () => {
|
||||
const ecpair = bchjs.ECPair.fromPublicKey(
|
||||
Buffer.from(fixture.pubkeyHex, "hex")
|
||||
)
|
||||
assert.equal(bchjs.HDNode.toCashAddress(ecpair), fixture.cashAddr)
|
||||
})
|
||||
|
||||
it(`should get ${fixture.regtestAddr} cash address`, () => {
|
||||
const ecpair = bchjs.ECPair.fromPublicKey(
|
||||
Buffer.from(fixture.pubkeyHex, "hex")
|
||||
)
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(ecpair, true),
|
||||
fixture.regtestAddr
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toPublicKey", () => {
|
||||
fixtures.toPublicKey.forEach(fixture => {
|
||||
it(`should create a public key buffer from an ECPair`, () => {
|
||||
const ecpair = bchjs.ECPair.fromPublicKey(
|
||||
Buffer.from(fixture.pubkeyHex, "hex")
|
||||
)
|
||||
const pubkeyBuffer = bchjs.ECPair.toPublicKey(ecpair)
|
||||
assert.equal(typeof pubkeyBuffer, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toLegacyAddress", () => {
|
||||
fixtures.toLegacyAddress.forEach(fixture => {
|
||||
it(`should create legacy address ${fixture.legacy} from an ECPair`, () => {
|
||||
const ecpair = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
const legacyAddress = bchjs.ECPair.toLegacyAddress(ecpair)
|
||||
assert.equal(legacyAddress, fixture.legacy)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toCashAddress", () => {
|
||||
fixtures.toCashAddress.forEach(fixture => {
|
||||
it(`should create cash address ${fixture.cashAddr} from an ECPair`, () => {
|
||||
const ecpair = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
const cashAddr = bchjs.ECPair.toCashAddress(ecpair)
|
||||
assert.equal(cashAddr, fixture.cashAddr)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.toCashAddress.forEach(fixture => {
|
||||
it(`should create regtest cash address ${fixture.regtestAddr} from an ECPair`, () => {
|
||||
const ecpair = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
const regtestAddr = bchjs.ECPair.toCashAddress(ecpair, true)
|
||||
assert.equal(regtestAddr, fixture.regtestAddr)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#sign", () => {
|
||||
fixtures.sign.forEach(fixture => {
|
||||
it(`should sign 32 byte hash buffer`, () => {
|
||||
const ecpair = bchjs.ECPair.fromWIF(fixture.privateKeyWIF)
|
||||
const buf = Buffer.from(bchjs.Crypto.sha256(fixture.data), "hex")
|
||||
const signatureBuf = bchjs.ECPair.sign(ecpair, buf)
|
||||
assert.equal(typeof signatureBuf, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#verify", () => {
|
||||
fixtures.verify.forEach(fixture => {
|
||||
it(`should verify signed 32 byte hash buffer`, () => {
|
||||
const ecpair1 = bchjs.ECPair.fromWIF(fixture.privateKeyWIF1)
|
||||
//const ecpair2 = bchjs.ECPair.fromWIF(fixture.privateKeyWIF2)
|
||||
const buf = Buffer.from(bchjs.Crypto.sha256(fixture.data), "hex")
|
||||
const signature = bchjs.ECPair.sign(ecpair1, buf)
|
||||
const verify = bchjs.ECPair.verify(ecpair1, buf, signature)
|
||||
assert.equal(verify, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,421 +0,0 @@
|
||||
const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const axios = require("axios")
|
||||
const sinon = require("sinon")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const mockData = require("./fixtures/electrumx-mock")
|
||||
|
||||
describe(`#ElectrumX`, () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe(`#utxo`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Electrumx.utxo(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.Electrumx.utxo(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "utxos")
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], "height")
|
||||
assert.property(result.utxos[0], "tx_hash")
|
||||
assert.property(result.utxos[0], "tx_pos")
|
||||
assert.property(result.utxos[0], "value")
|
||||
})
|
||||
|
||||
it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxos })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
const result = await bchjs.Electrumx.utxo(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "utxos")
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], "utxos")
|
||||
assert.isArray(result.utxos[0].utxos)
|
||||
assert.property(result.utxos[0], "address")
|
||||
|
||||
assert.property(result.utxos[0].utxos[0], "height")
|
||||
assert.property(result.utxos[0].utxos[0], "tx_hash")
|
||||
assert.property(result.utxos[0].utxos[0], "tx_pos")
|
||||
assert.property(result.utxos[0].utxos[0], "value")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#balance`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Electrumx.balance(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET balance for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.balance })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.Electrumx.balance(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "balance")
|
||||
assert.property(result.balance, "confirmed")
|
||||
assert.property(result.balance, "unconfirmed")
|
||||
})
|
||||
|
||||
it(`should POST balance for an array of addresses`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.balances })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
const result = await bchjs.Electrumx.balance(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "balances")
|
||||
assert.isArray(result.balances)
|
||||
|
||||
assert.property(result.balances[0], "address")
|
||||
assert.property(result.balances[0], "balance")
|
||||
assert.property(result.balances[0].balance, "confirmed")
|
||||
assert.property(result.balances[0].balance, "unconfirmed")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#transactions`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Electrumx.transactions(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET transactions for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.transaction })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.Electrumx.transactions(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "transactions")
|
||||
assert.isArray(result.transactions)
|
||||
assert.property(result.transactions[0], "height")
|
||||
assert.property(result.transactions[0], "tx_hash")
|
||||
})
|
||||
|
||||
it(`should POST transaction history for an array of addresses`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.transactions })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
const result = await bchjs.Electrumx.transactions(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "transactions")
|
||||
assert.isArray(result.transactions)
|
||||
|
||||
assert.property(result.transactions[0], "address")
|
||||
assert.property(result.transactions[0], "transactions")
|
||||
assert.isArray(result.transactions[0].transactions)
|
||||
assert.property(result.transactions[0].transactions[0], "height")
|
||||
assert.property(result.transactions[0].transactions[0], "tx_hash")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#unconfirmed`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Electrumx.unconfirmed(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET unconfirmed utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.unconfirmed })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.Electrumx.unconfirmed(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "utxos")
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], "height")
|
||||
assert.property(result.utxos[0], "tx_hash")
|
||||
assert.property(result.utxos[0], "fee")
|
||||
})
|
||||
|
||||
it(`should POST unconfirmed utxo details for an array of addresses`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.unconfirmedArray })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
const result = await bchjs.Electrumx.unconfirmed(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "utxos")
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], "utxos")
|
||||
assert.isArray(result.utxos[0].utxos)
|
||||
assert.property(result.utxos[0], "address")
|
||||
|
||||
assert.property(result.utxos[0].utxos[0], "height")
|
||||
assert.property(result.utxos[0].utxos[0], "tx_hash")
|
||||
assert.property(result.utxos[0].utxos[0], "fee")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#blockHeader`, () => {
|
||||
it(`should throw an error for improper height input`, async () => {
|
||||
try {
|
||||
// Mock network calls.
|
||||
sandbox.stub(axios, "get").rejects({
|
||||
response: {
|
||||
data: {
|
||||
success: false,
|
||||
error: "height must be a positive number"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const height = -10
|
||||
await bchjs.Electrumx.blockHeader(height)
|
||||
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(err.message, `height must be a positive number`)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should throw an error for improper count input`, async () => {
|
||||
try {
|
||||
// Mock network calls.
|
||||
sandbox.stub(axios, "get").rejects({
|
||||
response: {
|
||||
data: {
|
||||
success: false,
|
||||
error: "count must be a positive number"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const height = 42
|
||||
const count = -10
|
||||
|
||||
await bchjs.Electrumx.blockHeader(height, count)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(err.message, `count must be a positive number`)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET block headers for a given height`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.blockHeaders })
|
||||
|
||||
const height = 42
|
||||
|
||||
const result = await bchjs.Electrumx.blockHeader(height)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
assert.isArray(result)
|
||||
assert.equal(result.length, 2)
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#txData`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const txid = 12345
|
||||
|
||||
await bchjs.Electrumx.txData(txid)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input txId must be a string or array of strings`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET details data for a single transaction`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.details })
|
||||
|
||||
const txid =
|
||||
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
|
||||
|
||||
const result = await bchjs.Electrumx.txData(txid)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "details")
|
||||
assert.isObject(result.details)
|
||||
|
||||
assert.property(result.details, "blockhash")
|
||||
assert.property(result.details, "hash")
|
||||
assert.property(result.details, "hex")
|
||||
assert.property(result.details, "vin")
|
||||
assert.property(result.details, "vout")
|
||||
assert.equal(result.details.hash, txid)
|
||||
})
|
||||
|
||||
it(`should POST details for an array of transactions`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.detailsArray })
|
||||
|
||||
const txids = [
|
||||
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251",
|
||||
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
|
||||
]
|
||||
|
||||
const result = await bchjs.Electrumx.txData(txids)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "transactions")
|
||||
assert.isArray(result.transactions)
|
||||
|
||||
assert.property(result.transactions[0], "txid")
|
||||
assert.property(result.transactions[0], "details")
|
||||
|
||||
assert.property(result.transactions[0].details, "blockhash")
|
||||
assert.property(result.transactions[0].details, "hash")
|
||||
assert.property(result.transactions[0].details, "hex")
|
||||
assert.property(result.transactions[0].details, "vin")
|
||||
assert.property(result.transactions[0].details, "vout")
|
||||
|
||||
assert.equal(result.transactions.length, 2, "2 outputs for 2 inputs")
|
||||
})
|
||||
})
|
||||
describe(`#broadcast`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const txHex = 12345
|
||||
|
||||
await bchjs.Electrumx.broadcast(txHex)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(err.message, `Input txHex must be a string.`)
|
||||
}
|
||||
})
|
||||
it(`should broadcast a single transaction`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.broadcast })
|
||||
|
||||
const tx = mockData.details
|
||||
const txid = tx.details.txid
|
||||
const result = await bchjs.Electrumx.broadcast(tx.details.hex)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "txid")
|
||||
assert.equal(result.txid, txid)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,68 +0,0 @@
|
||||
const assert = require("chai").assert
|
||||
const sinon = require("sinon")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
// const bchjs = new BCHJS()
|
||||
let bchjs
|
||||
|
||||
const mockData = require("./fixtures/encryption-mock")
|
||||
|
||||
describe("#Encryption", () => {
|
||||
let sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe("#getPubKey", () => {
|
||||
it("should throw error if BCH address is not provided.", async () => {
|
||||
try {
|
||||
await bchjs.encryption.getPubKey()
|
||||
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
"Input must be a valid Bitcoin Cash address"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should report when public key can not be found", async () => {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(bchjs.encryption.axios, "get")
|
||||
.resolves({ data: mockData.failureMock })
|
||||
|
||||
const addr = "bitcoincash:qpxqr2pmcverj4vukgjqssvk2zju8tp9xsgz2nqagx"
|
||||
|
||||
const result = await bchjs.encryption.getPubKey(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, false)
|
||||
assert.property(result, "publicKey")
|
||||
assert.equal(result.publicKey, "not found")
|
||||
})
|
||||
|
||||
it("should get a public key", async () => {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(bchjs.encryption.axios, "get")
|
||||
.resolves({ data: mockData.successMock })
|
||||
|
||||
const addr = "bitcoincash:qpf8jv9hmqcda0502gjp7nm3g24y5h5s4unutghsxq"
|
||||
|
||||
const result = await bchjs.encryption.getPubKey(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
assert.property(result, "publicKey")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,28 +0,0 @@
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
describe("#Generating", () => {
|
||||
describe("#generateToAddress", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should generate", done => {
|
||||
const data = []
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "post").returns(resolved)
|
||||
|
||||
bchjs.Generating.generateToAddress(
|
||||
1,
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,345 +0,0 @@
|
||||
const fixtures = require("./fixtures/hdnode.json")
|
||||
const slpFixtures = require("./fixtures/slp/address.json")
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
describe("#HDNode", () => {
|
||||
describe("#fromSeed", () => {
|
||||
fixtures.fromSeed.forEach(mnemonic => {
|
||||
it(`should create an HDNode from root seed buffer`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#derive", () => {
|
||||
fixtures.derive.forEach(derive => {
|
||||
it(`should derive non hardened child HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(derive.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derive(hdNode, 0)
|
||||
assert.equal(bchjs.HDNode.toXPub(childHDNode), derive.xpub)
|
||||
assert.equal(bchjs.HDNode.toXPriv(childHDNode), derive.xpriv)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#deriveHardened", () => {
|
||||
fixtures.deriveHardened.forEach(derive => {
|
||||
it(`should derive hardened child HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(derive.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.deriveHardened(hdNode, 0)
|
||||
assert.equal(bchjs.HDNode.toXPub(childHDNode), derive.xpub)
|
||||
assert.equal(bchjs.HDNode.toXPriv(childHDNode), derive.xpriv)
|
||||
})
|
||||
})
|
||||
|
||||
describe("derive BIP44 $BCH account", () => {
|
||||
fixtures.deriveBIP44.forEach(derive => {
|
||||
it(`should derive BIP44 $BCH account`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(derive.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const purpose = bchjs.HDNode.deriveHardened(hdNode, 44)
|
||||
const coin = bchjs.HDNode.deriveHardened(purpose, 145)
|
||||
const childHDNode = bchjs.HDNode.deriveHardened(coin, 0)
|
||||
assert.equal(bchjs.HDNode.toXPub(childHDNode), derive.xpub)
|
||||
assert.equal(bchjs.HDNode.toXPriv(childHDNode), derive.xpriv)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#derivePath", () => {
|
||||
describe("derive non hardened Path", () => {
|
||||
fixtures.derivePath.forEach(derive => {
|
||||
it(`should derive non hardened child HDNode from path`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(derive.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derivePath(hdNode, "0")
|
||||
assert.equal(bchjs.HDNode.toXPub(childHDNode), derive.xpub)
|
||||
assert.equal(bchjs.HDNode.toXPriv(childHDNode), derive.xpriv)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("derive hardened Path", () => {
|
||||
fixtures.deriveHardenedPath.forEach(derive => {
|
||||
it(`should derive hardened child HDNode from path`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(derive.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derivePath(hdNode, "0'")
|
||||
assert.equal(bchjs.HDNode.toXPub(childHDNode), derive.xpub)
|
||||
assert.equal(bchjs.HDNode.toXPriv(childHDNode), derive.xpriv)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("derive BIP44 $BCH account", () => {
|
||||
fixtures.deriveBIP44.forEach(derive => {
|
||||
it(`should derive BIP44 $BCH account`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(derive.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derivePath(hdNode, "44'/145'/0'")
|
||||
assert.equal(bchjs.HDNode.toXPub(childHDNode), derive.xpub)
|
||||
assert.equal(bchjs.HDNode.toXPriv(childHDNode), derive.xpriv)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toLegacyAddress", () => {
|
||||
fixtures.toLegacyAddress.forEach(fixture => {
|
||||
it(`should get address ${fixture.address} from HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derivePath(hdNode, "0")
|
||||
const addy = bchjs.HDNode.toLegacyAddress(childHDNode)
|
||||
assert.equal(addy, fixture.address)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toCashAddress", () => {
|
||||
fixtures.toCashAddress.forEach(fixture => {
|
||||
it(`should get address ${fixture.address} from HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derivePath(hdNode, "0")
|
||||
const addy = bchjs.HDNode.toCashAddress(childHDNode)
|
||||
assert.equal(addy, fixture.address)
|
||||
})
|
||||
|
||||
it(`should get address ${fixture.regtestAddress} from HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const childHDNode = bchjs.HDNode.derivePath(hdNode, "0")
|
||||
const addr = bchjs.HDNode.toCashAddress(childHDNode, true)
|
||||
assert.equal(addr, fixture.regtestAddress)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toWIF", () => {
|
||||
fixtures.toWIF.forEach(fixture => {
|
||||
it(`should get privateKeyWIF ${fixture.privateKeyWIF} from HDNode`, () => {
|
||||
const hdNode = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
assert.equal(bchjs.HDNode.toWIF(hdNode), fixture.privateKeyWIF)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toXPub", () => {
|
||||
fixtures.toXPub.forEach(fixture => {
|
||||
it(`should create xpub ${fixture.xpub} from an HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const xpub = bchjs.HDNode.toXPub(hdNode)
|
||||
assert.equal(xpub, fixture.xpub)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toXPriv", () => {
|
||||
fixtures.toXPriv.forEach(fixture => {
|
||||
it(`should create xpriv ${fixture.xpriv} from an HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const xpriv = bchjs.HDNode.toXPriv(hdNode)
|
||||
assert.equal(xpriv, fixture.xpriv)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toKeyPair", () => {
|
||||
fixtures.toKeyPair.forEach(fixture => {
|
||||
it(`should get ECPair from an HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const keyPair = bchjs.HDNode.toKeyPair(hdNode)
|
||||
assert.equal(typeof keyPair, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toPublicKey", () => {
|
||||
fixtures.toPublicKey.forEach(fixture => {
|
||||
it(`should create public key buffer from an HDNode`, async () => {
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
const hdNode = bchjs.HDNode.fromSeed(rootSeedBuffer)
|
||||
const publicKeyBuffer = bchjs.HDNode.toPublicKey(hdNode)
|
||||
assert.equal(typeof publicKeyBuffer, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#fromXPriv", () => {
|
||||
fixtures.fromXPriv.forEach(fixture => {
|
||||
const hdNode = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
it(`should create HDNode from xpriv ${fixture.xpriv}`, () => {
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
|
||||
it(`should export xpriv ${fixture.xpriv}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPriv(hdNode), fixture.xpriv)
|
||||
})
|
||||
|
||||
it(`should export xpub ${fixture.xpub}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPub(hdNode), fixture.xpub)
|
||||
})
|
||||
|
||||
it(`should export legacy address ${fixture.legacy}`, () => {
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(hdNode), fixture.legacy)
|
||||
})
|
||||
|
||||
it(`should export cashaddress ${fixture.cashaddress}`, () => {
|
||||
assert.equal(bchjs.HDNode.toCashAddress(hdNode), fixture.cashaddress)
|
||||
})
|
||||
|
||||
it(`should export regtest cashaddress ${fixture.regtestaddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(hdNode, true),
|
||||
fixture.regtestaddress
|
||||
)
|
||||
})
|
||||
|
||||
it(`should export privateKeyWIF ${fixture.privateKeyWIF}`, () => {
|
||||
assert.equal(bchjs.HDNode.toWIF(hdNode), fixture.privateKeyWIF)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#fromXPub", () => {
|
||||
fixtures.fromXPub.forEach(fixture => {
|
||||
const hdNode = bchjs.HDNode.fromXPub(fixture.xpub)
|
||||
it(`should create HDNode from xpub ${fixture.xpub}`, () => {
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
|
||||
it(`should export xpub ${fixture.xpub}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPub(hdNode), fixture.xpub)
|
||||
})
|
||||
|
||||
it(`should export legacy address ${fixture.legacy}`, () => {
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(hdNode), fixture.legacy)
|
||||
})
|
||||
|
||||
it(`should export cashaddress ${fixture.cashaddress}`, () => {
|
||||
assert.equal(bchjs.HDNode.toCashAddress(hdNode), fixture.cashaddress)
|
||||
})
|
||||
|
||||
it(`should export regtest cashaddress ${fixture.regtestaddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(hdNode, true),
|
||||
fixture.regtestaddress
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#bip32", () => {
|
||||
describe("create accounts and addresses", () => {
|
||||
fixtures.accounts.forEach(async fixture => {
|
||||
const seedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
console.log(`seedBuffer: ${seedBuffer.toString()}`)
|
||||
const hdNode = bchjs.HDNode.fromSeed(seedBuffer)
|
||||
const a = bchjs.HDNode.derivePath(hdNode, "0'")
|
||||
const external = bchjs.HDNode.derivePath(a, "0")
|
||||
const account = bchjs.HDNode.createAccount([external])
|
||||
|
||||
it(`#createAccount`, () => {
|
||||
assert.notEqual(account, null)
|
||||
})
|
||||
|
||||
describe("#getChainAddress", () => {
|
||||
const external1 = bchjs.Address.toCashAddress(
|
||||
account.getChainAddress(0)
|
||||
)
|
||||
it(`should create external change address ${external1}`, () => {
|
||||
assert.equal(external1, fixture.externals[0])
|
||||
})
|
||||
})
|
||||
|
||||
describe("#nextChainAddress", () => {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const ex = bchjs.Address.toCashAddress(account.nextChainAddress(0))
|
||||
it(`should create external change address ${ex}`, () => {
|
||||
assert.equal(ex, fixture.externals[i + 1])
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#sign", () => {
|
||||
fixtures.sign.forEach(fixture => {
|
||||
it(`should sign 32 byte hash buffer`, () => {
|
||||
const hdnode = bchjs.HDNode.fromXPriv(fixture.privateKeyWIF)
|
||||
const buf = Buffer.from(bchjs.Crypto.sha256(fixture.data), "hex")
|
||||
const signatureBuf = bchjs.HDNode.sign(hdnode, buf)
|
||||
assert.equal(typeof signatureBuf, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#verify", () => {
|
||||
fixtures.verify.forEach(fixture => {
|
||||
it(`should verify signed 32 byte hash buffer`, () => {
|
||||
const hdnode1 = bchjs.HDNode.fromXPriv(fixture.privateKeyWIF1)
|
||||
const buf = Buffer.from(bchjs.Crypto.sha256(fixture.data), "hex")
|
||||
const signature = bchjs.HDNode.sign(hdnode1, buf)
|
||||
const verify = bchjs.HDNode.verify(hdnode1, buf, signature)
|
||||
assert.equal(verify, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isPublic", () => {
|
||||
fixtures.isPublic.forEach(fixture => {
|
||||
it(`should verify hdnode is public`, () => {
|
||||
const node = bchjs.HDNode.fromXPub(fixture.xpub)
|
||||
assert.equal(bchjs.HDNode.isPublic(node), true)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.isPublic.forEach(fixture => {
|
||||
it(`should verify hdnode is not public`, () => {
|
||||
const node = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
assert.equal(bchjs.HDNode.isPublic(node), false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isPrivate", () => {
|
||||
fixtures.isPrivate.forEach(fixture => {
|
||||
it(`should verify hdnode is not private`, () => {
|
||||
const node = bchjs.HDNode.fromXPub(fixture.xpub)
|
||||
assert.equal(bchjs.HDNode.isPrivate(node), false)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.isPrivate.forEach(fixture => {
|
||||
it(`should verify hdnode is private`, () => {
|
||||
const node = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
assert.equal(bchjs.HDNode.isPrivate(node), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toIdentifier", () => {
|
||||
fixtures.toIdentifier.forEach(fixture => {
|
||||
it(`should get identifier of hdnode`, () => {
|
||||
const node = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
const publicKeyBuffer = bchjs.HDNode.toPublicKey(node)
|
||||
const hash160 = bchjs.Crypto.hash160(publicKeyBuffer)
|
||||
const identifier = bchjs.HDNode.toIdentifier(node)
|
||||
assert.equal(identifier.toString("hex"), hash160.toString("hex"))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,443 +0,0 @@
|
||||
/*
|
||||
Unit tests for the IPFS Class.
|
||||
*/
|
||||
|
||||
const assert = require("chai").assert
|
||||
const sinon = require("sinon")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
let bchjs
|
||||
|
||||
const mockData = require("./fixtures/ipfs-mock")
|
||||
|
||||
describe(`#IPFS`, () => {
|
||||
let sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe("#initUppy", () => {
|
||||
it("should initialize uppy", () => {
|
||||
bchjs.IPFS.initUppy()
|
||||
})
|
||||
})
|
||||
|
||||
describe("#createFileModelServer", () => {
|
||||
it("should throw an error if file does not exist", async () => {
|
||||
try {
|
||||
const path = "/non-existant-file"
|
||||
|
||||
await bchjs.IPFS.createFileModelServer(path)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `Could not find this file`)
|
||||
}
|
||||
})
|
||||
|
||||
it("should create a new file model", async () => {
|
||||
const path = `${__dirname}/ipfs.js`
|
||||
|
||||
sandbox
|
||||
.stub(bchjs.IPFS.axios, "post")
|
||||
.resolves({ data: mockData.mockNewFileModel })
|
||||
|
||||
const result = await bchjs.IPFS.createFileModelServer(path)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "hostingCostBCH")
|
||||
assert.property(result, "hostingCostUSD")
|
||||
assert.property(result, "file")
|
||||
|
||||
assert.property(result.file, "payloadLink")
|
||||
assert.property(result.file, "hasBeenPaid")
|
||||
assert.property(result.file, "_id")
|
||||
assert.property(result.file, "schemaVersion")
|
||||
assert.property(result.file, "size")
|
||||
assert.property(result.file, "fileName")
|
||||
assert.property(result.file, "fileExtension")
|
||||
assert.property(result.file, "createdTimestamp")
|
||||
assert.property(result.file, "hostingCost")
|
||||
assert.property(result.file, "walletIndex")
|
||||
assert.property(result.file, "bchAddr")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#uploadFileServer", () => {
|
||||
it("should throw an error if file does not exist", async () => {
|
||||
try {
|
||||
const path = "/non-existant-file"
|
||||
|
||||
await bchjs.IPFS.uploadFileServer(path)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `Could not find this file`)
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw an error if modelId is not included", async () => {
|
||||
try {
|
||||
const path = `${__dirname}/ipfs.js`
|
||||
|
||||
await bchjs.IPFS.uploadFileServer(path)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `Must include a file model ID`)
|
||||
}
|
||||
})
|
||||
|
||||
it("Should throw error if the file was not uploaded", async () => {
|
||||
try {
|
||||
const mock = {
|
||||
successful: [],
|
||||
failed: [
|
||||
{
|
||||
id: "file id"
|
||||
}
|
||||
]
|
||||
}
|
||||
sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mock)
|
||||
|
||||
const path = `${__dirname}/ipfs.js`
|
||||
await bchjs.IPFS.uploadFileServer(path, "5ec562319bfacc745e8d8a52")
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(err)
|
||||
assert.include(err.message, `The file could not be uploaded`)
|
||||
}
|
||||
})
|
||||
|
||||
it("should return file object if the file is uploaded", async () => {
|
||||
try {
|
||||
sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mockData.uploadData)
|
||||
|
||||
const path = `${__dirname}/ipfs.js`
|
||||
const result = await bchjs.IPFS.uploadFileServer(
|
||||
path,
|
||||
"5ec562319bfacc745e8d8a52"
|
||||
)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "schemaVersion")
|
||||
assert.property(result, "size")
|
||||
assert.property(result, "fileId")
|
||||
assert.property(result, "fileName")
|
||||
assert.property(result, "fileExtension")
|
||||
} catch (err) {
|
||||
//console.log(err)
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getStatus", () => {
|
||||
it("should throw an error if modelId is not included", async () => {
|
||||
try {
|
||||
await bchjs.IPFS.getStatus()
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `Must include a file model ID`)
|
||||
}
|
||||
})
|
||||
|
||||
it("should get data on an unpaid file", async () => {
|
||||
const modelId = "5ec7392c2acfe57aa62e945a"
|
||||
|
||||
sandbox
|
||||
.stub(bchjs.IPFS.axios, "get")
|
||||
.resolves({ data: mockData.unpaidFileData })
|
||||
|
||||
const result = await bchjs.IPFS.getStatus(modelId)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "hasBeenPaid")
|
||||
assert.property(result, "satCost")
|
||||
assert.property(result, "bchAddr")
|
||||
assert.property(result, "ipfsHash")
|
||||
assert.property(result, "fileId")
|
||||
assert.property(result, "fileName")
|
||||
})
|
||||
|
||||
it("should get data on an unpaid file", async () => {
|
||||
const modelId = "5ec7392c2acfe57aa62e945a"
|
||||
|
||||
sandbox
|
||||
.stub(bchjs.IPFS.axios, "get")
|
||||
.resolves({ data: mockData.paidFileData })
|
||||
|
||||
const result = await bchjs.IPFS.getStatus(modelId)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "hasBeenPaid")
|
||||
assert.property(result, "satCost")
|
||||
assert.property(result, "bchAddr")
|
||||
assert.property(result, "ipfsHash")
|
||||
assert.property(result, "fileId")
|
||||
assert.property(result, "fileName")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#createFileModelWeb", () => {
|
||||
it("should throw an error if file is undefined", async () => {
|
||||
try {
|
||||
let file
|
||||
|
||||
await bchjs.IPFS.createFileModelWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `File is required`)
|
||||
}
|
||||
})
|
||||
it("should throw an error if file is empty", async () => {
|
||||
try {
|
||||
const file = {}
|
||||
|
||||
await bchjs.IPFS.createFileModelWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'name' of string type`
|
||||
)
|
||||
}
|
||||
})
|
||||
it("should throw an error if 'name' property is not included", async () => {
|
||||
try {
|
||||
const file = {
|
||||
size: 5000
|
||||
}
|
||||
|
||||
await bchjs.IPFS.createFileModelWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'name' of string type`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw an error if 'size' property is not included", async () => {
|
||||
try {
|
||||
const file = {
|
||||
name: "ipfs.js"
|
||||
}
|
||||
|
||||
await bchjs.IPFS.createFileModelWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'size' of number type`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should create a new file model", async () => {
|
||||
const file = {
|
||||
name: "ipfs.js",
|
||||
size: 5000,
|
||||
type: "text/plain"
|
||||
}
|
||||
sandbox
|
||||
.stub(bchjs.IPFS.axios, "post")
|
||||
.resolves({ data: mockData.mockNewFileModel })
|
||||
|
||||
const result = await bchjs.IPFS.createFileModelWeb(file)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "success")
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, "hostingCostBCH")
|
||||
assert.property(result, "hostingCostUSD")
|
||||
assert.property(result, "file")
|
||||
|
||||
assert.property(result.file, "payloadLink")
|
||||
assert.property(result.file, "hasBeenPaid")
|
||||
assert.property(result.file, "_id")
|
||||
assert.property(result.file, "schemaVersion")
|
||||
assert.property(result.file, "size")
|
||||
assert.property(result.file, "fileName")
|
||||
assert.property(result.file, "fileExtension")
|
||||
assert.property(result.file, "createdTimestamp")
|
||||
assert.property(result.file, "hostingCost")
|
||||
assert.property(result.file, "walletIndex")
|
||||
assert.property(result.file, "bchAddr")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#uploadFileWeb", () => {
|
||||
it("should throw an error if file is undefined", async () => {
|
||||
try {
|
||||
let file
|
||||
|
||||
await bchjs.IPFS.uploadFileWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `File is required`)
|
||||
}
|
||||
})
|
||||
it("should throw an error if file is empty", async () => {
|
||||
try {
|
||||
const file = {}
|
||||
|
||||
await bchjs.IPFS.uploadFileWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'name' of string type`
|
||||
)
|
||||
}
|
||||
})
|
||||
it("should throw an error if 'name' property is not included", async () => {
|
||||
try {
|
||||
const file = {
|
||||
size: 5000,
|
||||
type: "text/plain"
|
||||
}
|
||||
|
||||
await bchjs.IPFS.uploadFileWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'name' of string type`
|
||||
)
|
||||
}
|
||||
})
|
||||
it("should throw an error if 'size' property is not included", async () => {
|
||||
try {
|
||||
const file = {
|
||||
name: "ipfs.js",
|
||||
type: "text/plain"
|
||||
}
|
||||
|
||||
await bchjs.IPFS.uploadFileWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'size' of number type`
|
||||
)
|
||||
}
|
||||
})
|
||||
it("should throw an error if 'type' property is not included", async () => {
|
||||
try {
|
||||
const file = {
|
||||
name: "ipfs.js",
|
||||
size: 5000
|
||||
}
|
||||
|
||||
await bchjs.IPFS.uploadFileWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(
|
||||
err.message,
|
||||
`File should have the property 'type' of string type`
|
||||
)
|
||||
}
|
||||
})
|
||||
it("should throw an error if modelId is not included", async () => {
|
||||
try {
|
||||
const file = {
|
||||
name: "ipfs.js",
|
||||
size: 5000,
|
||||
type: "text/plain"
|
||||
}
|
||||
await bchjs.IPFS.uploadFileWeb(file)
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(`err.message: ${err.message}`)
|
||||
assert.include(err.message, `Must include a file model ID`)
|
||||
}
|
||||
})
|
||||
|
||||
it("Should throw error if the file was not uploaded", async () => {
|
||||
try {
|
||||
const mock = {
|
||||
successful: [],
|
||||
failed: [
|
||||
{
|
||||
id: "file id"
|
||||
}
|
||||
]
|
||||
}
|
||||
sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mock)
|
||||
|
||||
const file = {
|
||||
name: "ipfs.js",
|
||||
size: 5000,
|
||||
type: "text/plain"
|
||||
}
|
||||
await bchjs.IPFS.uploadFileWeb(file, "5ec562319bfacc745e8d8a52")
|
||||
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
} catch (err) {
|
||||
//console.log(err)
|
||||
assert.include(err.message, `The file could not be uploaded`)
|
||||
}
|
||||
})
|
||||
|
||||
it("should return file object if the file is uploaded", async () => {
|
||||
try {
|
||||
sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mockData.uploadData)
|
||||
|
||||
const file = {
|
||||
name: "ipfs.js",
|
||||
size: 5000,
|
||||
type: "text/plain"
|
||||
}
|
||||
const result = await bchjs.IPFS.uploadFileWeb(
|
||||
file,
|
||||
"5ec562319bfacc745e8d8a52"
|
||||
)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "schemaVersion")
|
||||
assert.property(result, "size")
|
||||
assert.property(result, "fileId")
|
||||
assert.property(result, "fileName")
|
||||
assert.property(result, "fileExtension")
|
||||
} catch (err) {
|
||||
//console.log(err)
|
||||
assert.equal(true, false, "Unexpected result")
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,104 +0,0 @@
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
describe("#Mining", () => {
|
||||
describe("#getBlockTemplate", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get block template", done => {
|
||||
const data = {
|
||||
data:
|
||||
"01000000017f6305e3b0b05f5b57a82f4e6d4187e148bbe56a947208390e488bad36472368000000006a47304402203b0079ff5b896187feb02e2679c87ac2fb8d483b60e0721ed33601e2c0eecc700220590f8a0e1a51b53b368294861fd5fc99db3a6607d0f4e543f6217108e208c1834121024c93c841d7f576584ffbf513b7abd8283e6562669905f6554f788fce4cc67a34ffffffff0228100000000000001976a914af78709a76abc8a28e568c9210c8247dd10cff2c88ac22020000000000001976a914f339927678803f451b41400737e7dc83c6a8682188ac00000000",
|
||||
txid:
|
||||
"7f462d71c649a0d8cfbaa2d20d8ff86677966b308f0ac9906ee015bf4453f97a",
|
||||
hash:
|
||||
"7f462d71c649a0d8cfbaa2d20d8ff86677966b308f0ac9906ee015bf4453f97a",
|
||||
depends: [],
|
||||
fee: 226,
|
||||
sigops: 2
|
||||
}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Mining.getBlockTemplate("")
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getMiningInfo", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get mining info", done => {
|
||||
const data = {
|
||||
blocks: 527816,
|
||||
currentblocksize: 89408,
|
||||
currentblocktx: 156,
|
||||
difficulty: 568757800682.7649,
|
||||
blockprioritypercentage: 5,
|
||||
errors: "",
|
||||
networkhashps: 4347259225696976000,
|
||||
pooledtx: 184,
|
||||
chain: "main"
|
||||
}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Mining.getMiningInfo()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getNetworkHashps", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get network hashps", done => {
|
||||
const data = 3586365937646890000
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Mining.getNetworkHashps()
|
||||
.then(result => {
|
||||
assert.equal(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#submitBlock", () => {
|
||||
// TODO finish
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should TODO", done => {
|
||||
const data = {}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "post").returns(resolved)
|
||||
|
||||
bchjs.Mining.submitBlock()
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,340 +0,0 @@
|
||||
const fixtures = require("./fixtures/mnemonic.json")
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
describe("#Mnemonic", () => {
|
||||
describe("#generate", () => {
|
||||
it("should generate a 12 word mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(128)
|
||||
assert.equal(mnemonic.split(" ").length, 12)
|
||||
})
|
||||
|
||||
it("should generate a 15 word mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(160)
|
||||
assert.equal(mnemonic.split(" ").length, 15)
|
||||
})
|
||||
|
||||
it("should generate a 18 word mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(192)
|
||||
assert.equal(mnemonic.split(" ").length, 18)
|
||||
})
|
||||
|
||||
it("should generate an 21 word mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(224)
|
||||
assert.equal(mnemonic.split(" ").length, 21)
|
||||
})
|
||||
|
||||
it("should generate an 24 word mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(256)
|
||||
assert.equal(mnemonic.split(" ").length, 24)
|
||||
})
|
||||
|
||||
it("should generate an 24 word italian mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(
|
||||
256,
|
||||
bchjs.Mnemonic.wordLists().italian
|
||||
)
|
||||
assert.equal(mnemonic.split(" ").length, 24)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#fromEntropy", () => {
|
||||
it("should generate a 12 word mnemonic from 16 bytes of entropy", () => {
|
||||
const rand = bchjs.Crypto.randomBytes(16)
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(rand.toString("hex"))
|
||||
assert.equal(mnemonic.split(" ").length, 12)
|
||||
})
|
||||
|
||||
it("should generate a 15 word mnemonic from 20 bytes of entropy", () => {
|
||||
const rand = bchjs.Crypto.randomBytes(20)
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(rand.toString("hex"))
|
||||
assert.equal(mnemonic.split(" ").length, 15)
|
||||
})
|
||||
|
||||
it("should generate an 18 word mnemonic from 24 bytes of entropy", () => {
|
||||
const rand = bchjs.Crypto.randomBytes(24)
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(rand.toString("hex"))
|
||||
assert.equal(mnemonic.split(" ").length, 18)
|
||||
})
|
||||
|
||||
it("should generate an 21 word mnemonic from 28 bytes of entropy", () => {
|
||||
const rand = bchjs.Crypto.randomBytes(28)
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(rand.toString("hex"))
|
||||
assert.equal(mnemonic.split(" ").length, 21)
|
||||
})
|
||||
|
||||
it("should generate an 24 word mnemonic from 32 bytes of entropy", () => {
|
||||
const rand = bchjs.Crypto.randomBytes(32)
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(rand.toString("hex"))
|
||||
assert.equal(mnemonic.split(" ").length, 24)
|
||||
})
|
||||
|
||||
it("should generate an 24 french word mnemonic 32 bytes of entropy", () => {
|
||||
const rand = bchjs.Crypto.randomBytes(32)
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(
|
||||
rand.toString("hex"),
|
||||
bchjs.Mnemonic.wordLists().french
|
||||
)
|
||||
assert.equal(mnemonic.split(" ").length, 24)
|
||||
})
|
||||
|
||||
fixtures.fromEntropy.forEach(entropy => {
|
||||
const mnemonic = bchjs.Mnemonic.fromEntropy(entropy.entropy)
|
||||
it(`should convert ${entropy.entropy} to ${entropy.mnemonic}`, () => {
|
||||
assert.equal(mnemonic, entropy.mnemonic)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toEntropy", () => {
|
||||
it("should turn a 12 word mnemonic to entropy", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(128)
|
||||
const entropy = bchjs.Mnemonic.toEntropy(mnemonic)
|
||||
assert.equal(entropy.length, 16)
|
||||
})
|
||||
|
||||
it("should turn a 15 word mnemonic to entropy", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(160)
|
||||
const entropy = bchjs.Mnemonic.toEntropy(mnemonic)
|
||||
assert.equal(entropy.length, 20)
|
||||
})
|
||||
|
||||
it("should turn a 18 word mnemonic to entropy", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(192)
|
||||
const entropy = bchjs.Mnemonic.toEntropy(mnemonic)
|
||||
assert.equal(entropy.length, 24)
|
||||
})
|
||||
|
||||
it("should turn a 21 word mnemonic to entropy", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(224)
|
||||
const entropy = bchjs.Mnemonic.toEntropy(mnemonic)
|
||||
assert.equal(entropy.length, 28)
|
||||
})
|
||||
|
||||
it("should turn a 24 word mnemonic to entropy", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(256)
|
||||
const entropy = bchjs.Mnemonic.toEntropy(mnemonic)
|
||||
assert.equal(entropy.length, 32)
|
||||
})
|
||||
|
||||
it("should turn a 24 word spanish mnemonic to entropy", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(
|
||||
256,
|
||||
bchjs.Mnemonic.wordLists().spanish
|
||||
)
|
||||
const entropy = bchjs.Mnemonic.toEntropy(
|
||||
mnemonic,
|
||||
bchjs.Mnemonic.wordLists().spanish
|
||||
)
|
||||
assert.equal(entropy.length, 32)
|
||||
})
|
||||
|
||||
fixtures.fromEntropy.forEach(fixture => {
|
||||
const entropy = bchjs.Mnemonic.toEntropy(fixture.mnemonic)
|
||||
it(`should convert ${fixture.mnemonic} to ${fixture.entropy}`, () => {
|
||||
assert.equal(entropy.toString("hex"), fixture.entropy)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#validate", () => {
|
||||
it("fails for a mnemonic that is too short", () => {
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(
|
||||
"mixed winner",
|
||||
bchjs.Mnemonic.wordLists().english
|
||||
),
|
||||
"Invalid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("fails for a mnemonic that is too long", () => {
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(
|
||||
"mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake mixed winner decide drift danger together twice planet impose asthma catch require select mask awkward spy relief front work solar pitch economy render cake",
|
||||
bchjs.Mnemonic.wordLists().english
|
||||
),
|
||||
"Invalid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("fails if mnemonic words are not in the word list", () => {
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(
|
||||
"failsauce one two three four five six seven eight nine ten eleven",
|
||||
bchjs.Mnemonic.wordLists().english
|
||||
),
|
||||
"failsauce is not in wordlist, did you mean balance?"
|
||||
)
|
||||
})
|
||||
|
||||
it("validate a 128 bit mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(128)
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(mnemonic, bchjs.Mnemonic.wordLists().english),
|
||||
"Valid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("validate a 160 bit mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(160)
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(mnemonic, bchjs.Mnemonic.wordLists().english),
|
||||
"Valid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("validate a 192 bit mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(192)
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(mnemonic, bchjs.Mnemonic.wordLists().english),
|
||||
"Valid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("validate a 224 bit mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(224)
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(mnemonic, bchjs.Mnemonic.wordLists().english),
|
||||
"Valid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("validate a 256 bit mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(256)
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(mnemonic, bchjs.Mnemonic.wordLists().english),
|
||||
"Valid mnemonic"
|
||||
)
|
||||
})
|
||||
|
||||
it("validate a 256 bit chinese simplified mnemonic", () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(
|
||||
256,
|
||||
bchjs.Mnemonic.wordLists().chinese_simplified
|
||||
)
|
||||
assert.equal(
|
||||
bchjs.Mnemonic.validate(
|
||||
mnemonic,
|
||||
bchjs.Mnemonic.wordLists().chinese_simplified
|
||||
),
|
||||
"Valid mnemonic"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toSeed", () => {
|
||||
it("should create 512 bit / 64 byte HMAC-SHA512 root seed from a 128 bit mnemonic", async () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(128)
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(mnemonic, "")
|
||||
assert.equal(rootSeedBuffer.byteLength, 64)
|
||||
})
|
||||
|
||||
it("should create 512 bit / 64 byte HMAC-SHA512 root seed from a 160 bit mnemonic", async () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(160)
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(mnemonic, "")
|
||||
assert.equal(rootSeedBuffer.byteLength, 64)
|
||||
})
|
||||
|
||||
it("should create 512 bit / 64 byte HMAC-SHA512 root seed from a 192 bit mnemonic", async () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(192)
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(mnemonic, "")
|
||||
assert.equal(rootSeedBuffer.byteLength, 64)
|
||||
})
|
||||
|
||||
it("should create 512 bit / 64 byte HMAC-SHA512 root seed from a 224 bit mnemonic", async () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(224)
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(mnemonic, "")
|
||||
assert.equal(rootSeedBuffer.byteLength, 64)
|
||||
})
|
||||
|
||||
it("should create 512 bit / 64 byte HMAC-SHA512 root seed from a 256 bit mnemonic", async () => {
|
||||
const mnemonic = bchjs.Mnemonic.generate(256)
|
||||
const rootSeedBuffer = await bchjs.Mnemonic.toSeed(mnemonic, "")
|
||||
assert.equal(rootSeedBuffer.byteLength, 64)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#wordLists", () => {
|
||||
it("return a list of 2048 english words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().english.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 japanese words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().japanese.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 chinese simplified words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().chinese_simplified.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 chinese traditional words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().chinese_traditional.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 french words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().french.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 italian words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().italian.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 korean words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().korean.length, 2048)
|
||||
})
|
||||
|
||||
it("return a list of 2048 spanish words", () => {
|
||||
assert.equal(bchjs.Mnemonic.wordLists().spanish.length, 2048)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toKeypairs", async () => {
|
||||
fixtures.toKeypairs.forEach(async (fixture, i) => {
|
||||
const keypairs = await bchjs.Mnemonic.toKeypairs(fixture.mnemonic, 5)
|
||||
keypairs.forEach((keypair, j) => {
|
||||
it(`Generate keypair from mnemonic`, () => {
|
||||
assert.equal(
|
||||
keypair.privateKeyWIF,
|
||||
fixtures.toKeypairs[i].output[j].privateKeyWIF
|
||||
)
|
||||
// assert.equal(
|
||||
// keypair.address,
|
||||
// fixtures.toKeypairs[i].output[j].address
|
||||
// )
|
||||
})
|
||||
})
|
||||
|
||||
const regtestKeypairs = await bchjs.Mnemonic.toKeypairs(
|
||||
fixture.mnemonic,
|
||||
5,
|
||||
true
|
||||
)
|
||||
regtestKeypairs.forEach((keypair, j) => {
|
||||
it(`Generate keypair from mnemonic`, () => {
|
||||
assert.equal(
|
||||
keypair.privateKeyWIF,
|
||||
fixtures.toKeypairs[i].output[j].privateKeyWIFRegTest
|
||||
)
|
||||
// assert.equal(
|
||||
// keypair.address,
|
||||
// fixtures.toKeypairs[i].output[j].regtestAddress
|
||||
// )
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#findNearestWord", () => {
|
||||
fixtures.findNearestWord.forEach((fixture, i) => {
|
||||
const word = bchjs.Mnemonic.findNearestWord(
|
||||
fixture.word,
|
||||
bchjs.Mnemonic.wordLists()[fixture.language]
|
||||
)
|
||||
it(`find word ${fixture.foundWord} near ${fixture.word} in ${fixture.language}`, () => {
|
||||
assert.equal(word, fixture.foundWord)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,255 +0,0 @@
|
||||
const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const axios = require("axios")
|
||||
const sinon = require("sinon")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const mockData = require("./fixtures/ninsight-mock")
|
||||
|
||||
describe(`#Ninsight`, () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe(`#utxo`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.utxo(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings.`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.Ninsight.utxo(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "utxos")
|
||||
assert.property(result, "legacyAddress")
|
||||
assert.property(result, "cashAddress")
|
||||
assert.property(result, "slpAddress")
|
||||
assert.property(result, "scriptPubKey")
|
||||
assert.property(result, "asm")
|
||||
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], "txid")
|
||||
assert.property(result.utxos[0], "vout")
|
||||
assert.property(result.utxos[0], "amount")
|
||||
assert.property(result.utxos[0], "satoshis")
|
||||
assert.property(result.utxos[0], "height")
|
||||
assert.property(result.utxos[0], "confirmations")
|
||||
})
|
||||
|
||||
it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxoPost })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.utxo(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.isArray(result[0].utxos)
|
||||
|
||||
assert.property(result[0], "utxos")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "slpAddress")
|
||||
assert.property(result[0], "scriptPubKey")
|
||||
assert.property(result[0], "asm")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#unconfirmed", () => {
|
||||
it("should throw an error for improper input", async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.unconfirmed(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
"Input address must be a string or array of strings."
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should POST utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.unconfirmed })
|
||||
|
||||
const addr = "bitcoincash:qpkkjkhe29mqhqmu3evtq3dsnruuzl3rku6usknlh5"
|
||||
|
||||
const result = await bchjs.Ninsight.unconfirmed(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "utxos")
|
||||
assert.property(result, "legacyAddress")
|
||||
assert.property(result, "cashAddress")
|
||||
assert.property(result, "slpAddress")
|
||||
assert.property(result, "scriptPubKey")
|
||||
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], "txid")
|
||||
assert.property(result.utxos[0], "vout")
|
||||
assert.property(result.utxos[0], "amount")
|
||||
assert.property(result.utxos[0], "satoshis")
|
||||
assert.property(result.utxos[0], "confirmations")
|
||||
assert.property(result.utxos[0], "ts")
|
||||
})
|
||||
|
||||
it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.unconfirmedPost })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qpkkjkhe29mqhqmu3evtq3dsnruuzl3rku6usknlh5",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.unconfirmed(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.isArray(result[0].utxos)
|
||||
|
||||
assert.property(result[0], "utxos")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "slpAddress")
|
||||
assert.property(result[0], "scriptPubKey")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#transactions`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.transactions(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Input address must be a string or array of strings.`
|
||||
)
|
||||
}
|
||||
})
|
||||
it(`should POST transaction history for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.transactionsPost })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.Ninsight.transactions(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "txs")
|
||||
assert.isArray(result[0].txs)
|
||||
assert.property(result[0].txs[0], "txid")
|
||||
assert.property(result[0].txs[0], "vin")
|
||||
assert.property(result[0].txs[0], "vout")
|
||||
})
|
||||
it(`should POST transaction history for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.transactionsPost })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.transactions(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "txs")
|
||||
assert.isArray(result[0].txs)
|
||||
assert.property(result[0].txs[0], "txid")
|
||||
})
|
||||
})
|
||||
describe(`#txDetails`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const txid = 12345
|
||||
|
||||
await bchjs.Ninsight.txDetails(txid)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(
|
||||
err.message,
|
||||
`Transaction ID must be a string or array of strings.`
|
||||
)
|
||||
}
|
||||
})
|
||||
it(`should POST transaction details for a single TxID`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.detailsPost })
|
||||
|
||||
const txid = "fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33"
|
||||
|
||||
const result = await bchjs.Ninsight.txDetails(txid)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "txid")
|
||||
assert.property(result[0], "version")
|
||||
assert.property(result[0], "locktime")
|
||||
assert.property(result[0], "vin")
|
||||
assert.property(result[0], "vout")
|
||||
assert.property(result[0], "blockhash")
|
||||
assert.property(result[0], "blockheight")
|
||||
assert.property(result[0], "confirmations")
|
||||
assert.property(result[0], "time")
|
||||
assert.property(result[0], "blocktime")
|
||||
assert.property(result[0], "isCoinBase")
|
||||
assert.property(result[0], "valueOut")
|
||||
assert.property(result[0], "size")
|
||||
})
|
||||
it(`should POST transaction details for an array of TxIDs`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.detailsPost })
|
||||
|
||||
const txid = [
|
||||
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
|
||||
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.txDetails(txid)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "txid")
|
||||
assert.property(result[0], "vin")
|
||||
assert.property(result[0], "vout")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,129 +0,0 @@
|
||||
const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const axios = require("axios")
|
||||
const sinon = require("sinon")
|
||||
|
||||
const mockData = require("./fixtures/openbazaar-mock")
|
||||
|
||||
describe(`#OpenBazaar`, () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe(`#Balance`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.OpenBazaar.balance(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(err.message, `Input address must be a string`)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET balance for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.balance })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.OpenBazaar.balance(addr)
|
||||
//console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.hasAllKeys(result, [
|
||||
"page",
|
||||
"totalPages",
|
||||
"itemsOnPage",
|
||||
"addrStr",
|
||||
"balance",
|
||||
"totalReceived",
|
||||
"totalSent",
|
||||
"unconfirmedBalance",
|
||||
"unconfirmedTxApperances",
|
||||
"txApperances",
|
||||
"transactions"
|
||||
])
|
||||
assert.isArray(result.transactions)
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#utxo`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.OpenBazaar.utxo(addr)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(err.message, `Input address must be a string`)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
const result = await bchjs.OpenBazaar.utxo(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.hasAllKeys(result[0], [
|
||||
"txid",
|
||||
"vout",
|
||||
"amount",
|
||||
"height",
|
||||
"confirmations",
|
||||
"satoshis"
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#tx`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const txid = 12345
|
||||
|
||||
await bchjs.OpenBazaar.tx(txid)
|
||||
assert.equal(true, false, "Unexpected result!")
|
||||
} catch (err) {
|
||||
//console.log(`err: `, err)
|
||||
assert.include(err.message, `Input txid must be a string`)
|
||||
}
|
||||
})
|
||||
|
||||
it(`should GET tx details for a single txid`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.tx })
|
||||
|
||||
const txid =
|
||||
"2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7"
|
||||
|
||||
const result = await bchjs.OpenBazaar.tx(txid)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, [
|
||||
"txid",
|
||||
"version",
|
||||
"vin",
|
||||
"vout",
|
||||
"blockhash",
|
||||
"blockheight",
|
||||
"confirmations",
|
||||
"blocktime",
|
||||
"valueOut",
|
||||
"valueIn",
|
||||
"fees",
|
||||
"hex"
|
||||
])
|
||||
assert.isArray(result.vin)
|
||||
assert.isArray(result.vout)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
TODO:
|
||||
-Replace old unit tests mocking axios with the more generalized nock library.
|
||||
See the sendRawTransaction test for an example.
|
||||
-Create a mocking library of data to compare unit and integration tests.
|
||||
*/
|
||||
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const sinon = require("sinon")
|
||||
const nock = require("nock") // HTTP mocking
|
||||
|
||||
// Used for debugging
|
||||
const util = require("util")
|
||||
util.inspect.defaultOptions = { depth: 1 }
|
||||
|
||||
describe("#RawTransactions", () => {
|
||||
describe("#decodeRawTransaction", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should decode raw transaction", done => {
|
||||
const data = {
|
||||
txid:
|
||||
"4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a",
|
||||
hash:
|
||||
"4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a",
|
||||
size: 10,
|
||||
version: 2,
|
||||
locktime: 0,
|
||||
vin: [],
|
||||
vout: []
|
||||
}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.RawTransactions.decodeRawTransaction("02000000000000000000")
|
||||
.then(result => {
|
||||
assert.equal(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#decodeScript", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should decode script", async () => {
|
||||
const data = {
|
||||
asm: "OP_RETURN 5361746f736869204e616b616d6f746f",
|
||||
type: "nulldata",
|
||||
p2sh: "bitcoincash:prswx5965nfumux9qng5kj8hw603vcne7q08t8c6jp"
|
||||
}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
const result = await bchjs.RawTransactions.decodeScript(
|
||||
"6a105361746f736869204e616b616d6f746f"
|
||||
)
|
||||
//console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getRawTransaction", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get raw transaction", done => {
|
||||
const data =
|
||||
"020000000160d663961c63c7f0a07f22ec07b8f55b3935bfdbed8b1d8454916e8932fbf109010000006b4830450221008479fab4cfdcb111833d250a43f98ac26d43272b7a29cb1b9a0491eae5c44b3502203448b17253632395c29a7d62058bbfe93efb20fc8636ba6837002d464195aec04121029123258f7cdcd45b864066bcaa9b71f24d5ed1fa1dd36eaf107d8432b5014658ffffffff016d180000000000001976a91479d3297d1823149f4ec61df31d19f2fad5390c0288ac00000000"
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.RawTransactions.getRawTransaction(
|
||||
"808d617eccaad4f1397fe07a06ec5ed15a0821cf22a3e0931c0c92aef9e572b6"
|
||||
)
|
||||
.then(result => {
|
||||
assert.equal(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#sendRawTransaction", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should send single raw transaction", async () => {
|
||||
const data = "Error: transaction already in block chain"
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
const result = await bchjs.RawTransactions.sendRawTransaction(
|
||||
"020000000160d663961c63c7f0a07f22ec07b8f55b3935bfdbed8b1d8454916e8932fbf109010000006b4830450221008479fab4cfdcb111833d250a43f98ac26d43272b7a29cb1b9a0491eae5c44b3502203448b17253632395c29a7d62058bbfe93efb20fc8636ba6837002d464195aec04121029123258f7cdcd45b864066bcaa9b71f24d5ed1fa1dd36eaf107d8432b5014658ffffffff016d180000000000001976a91479d3297d1823149f4ec61df31d19f2fad5390c0288ac00000000"
|
||||
)
|
||||
|
||||
assert.equal(data, result)
|
||||
})
|
||||
|
||||
it("should send an array of raw transactions", async () => {
|
||||
const data = "Error: transaction already in block chain"
|
||||
|
||||
// Mock the http call to rest.bitcoin.com
|
||||
nock(`${bchjs.RawTransactions.restURL}`)
|
||||
.post(uri => uri.includes(`/`))
|
||||
.reply(200, { data: data })
|
||||
|
||||
const result = await bchjs.RawTransactions.sendRawTransaction([
|
||||
"020000000160d663961c63c7f0a07f22ec07b8f55b3935bfdbed8b1d8454916e8932fbf109010000006b4830450221008479fab4cfdcb111833d250a43f98ac26d43272b7a29cb1b9a0491eae5c44b3502203448b17253632395c29a7d62058bbfe93efb20fc8636ba6837002d464195aec04121029123258f7cdcd45b864066bcaa9b71f24d5ed1fa1dd36eaf107d8432b5014658ffffffff016d180000000000001976a91479d3297d1823149f4ec61df31d19f2fad5390c0288ac00000000"
|
||||
])
|
||||
|
||||
assert.equal(data, result.data)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,476 +0,0 @@
|
||||
const fixtures = require("./fixtures/script.json")
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
describe("#Script", () => {
|
||||
describe("#decode", () => {
|
||||
describe("P2PKH scriptSig", () => {
|
||||
fixtures.decodeScriptSig.forEach(fixture => {
|
||||
it(`should decode scriptSig buffer`, () => {
|
||||
const decodedScriptSig = bchjs.Script.decode(
|
||||
Buffer.from(fixture.scriptSigHex, "hex")
|
||||
)
|
||||
assert.equal(typeof decodedScriptSig, "object")
|
||||
})
|
||||
|
||||
it(`should decode scriptSig buffer to cash address ${fixture.cashAddress}`, () => {
|
||||
const decodedScriptSig = bchjs.Script.decode(
|
||||
Buffer.from(fixture.scriptSigHex, "hex")
|
||||
)
|
||||
const address = bchjs.HDNode.toCashAddress(
|
||||
bchjs.ECPair.fromPublicKey(decodedScriptSig[1])
|
||||
)
|
||||
assert.equal(address, fixture.cashAddress)
|
||||
})
|
||||
|
||||
it(`should decode scriptSig buffer to legacy address ${fixture.legacyAddress}`, () => {
|
||||
const decodedScriptSig = bchjs.Script.decode(
|
||||
Buffer.from(fixture.scriptSigHex, "hex")
|
||||
)
|
||||
const address = bchjs.HDNode.toLegacyAddress(
|
||||
bchjs.ECPair.fromPublicKey(decodedScriptSig[1])
|
||||
)
|
||||
assert.equal(address, fixture.legacyAddress)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("P2PKH scriptPubKey", () => {
|
||||
fixtures.decodeScriptPubKey.forEach(fixture => {
|
||||
it(`should decode scriptSig buffer`, () => {
|
||||
const decodedScriptPubKey = bchjs.Script.decode(
|
||||
Buffer.from(fixture.scriptPubKeyHex, "hex")
|
||||
)
|
||||
assert.equal(decodedScriptPubKey.length, 5)
|
||||
})
|
||||
|
||||
it(`should match hashed pubKey ${fixture.pubKeyHex}`, () => {
|
||||
const decodedScriptPubKey = bchjs.Script.decode(
|
||||
Buffer.from(fixture.scriptPubKeyHex, "hex")
|
||||
)
|
||||
const data = Buffer.from(fixture.pubKeyHex, "hex")
|
||||
const hash160 = bchjs.Crypto.hash160(data).toString("hex")
|
||||
assert.equal(decodedScriptPubKey[2].toString("hex"), hash160)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#encode", () => {
|
||||
describe("P2PKH scriptSig", () => {
|
||||
fixtures.encodeScriptSig.forEach(fixture => {
|
||||
it(`should encode scriptSig chunks to buffer`, () => {
|
||||
const arr = [
|
||||
Buffer.from(fixture.scriptSigChunks[0], "hex"),
|
||||
Buffer.from(fixture.scriptSigChunks[1], "hex")
|
||||
]
|
||||
const encodedScriptSig = bchjs.Script.encode(arr)
|
||||
assert.equal(typeof encodedScriptSig, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("P2PKH scriptPubKey", () => {
|
||||
fixtures.encodeScriptPubKey.forEach(fixture => {
|
||||
it(`should encode scriptPubKey buffer`, () => {
|
||||
const decodedScriptPubKey = bchjs.Script.decode(
|
||||
Buffer.from(fixture.scriptPubKeyHex, "hex")
|
||||
)
|
||||
const compiledScriptPubKey = bchjs.Script.encode(decodedScriptPubKey)
|
||||
assert.equal(
|
||||
compiledScriptPubKey.toString("hex"),
|
||||
fixture.scriptPubKeyHex
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("Encode SLP SEND OP_RETURN properly", () => {
|
||||
it("should correctly compile OP_RETURN SLP SEND transaction", () => {
|
||||
const scriptArr = [
|
||||
bchjs.Script.opcodes.OP_RETURN,
|
||||
Buffer.from("534c5000", "hex"),
|
||||
Buffer.from("01", "hex"),
|
||||
Buffer.from(`SEND`),
|
||||
Buffer.from(
|
||||
"73db55368981e4878440637e448d4abe7f661be5c3efdcbcb63bd86a01a76b5a",
|
||||
"hex"
|
||||
),
|
||||
Buffer.from("00000001", "hex")
|
||||
]
|
||||
|
||||
const data = bchjs.Script.encode2(scriptArr)
|
||||
|
||||
// convert data to a hex string
|
||||
let str = ""
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let hex = Number(data[i]).toString(16)
|
||||
|
||||
// zero pad when its a single digit.
|
||||
hex = `0${hex}`
|
||||
hex = hex.slice(-2)
|
||||
//console.log(`hex: ${hex}`)
|
||||
|
||||
str += hex
|
||||
}
|
||||
console.log(`Hex string: ${str}`)
|
||||
|
||||
//console.log(`scriptArr: ${JSON.stringify(data,null,2)}`)
|
||||
|
||||
const correctStr =
|
||||
"6a04534c500001010453454e442073db55368981e4878440637e448d4abe7f661be5c3efdcbcb63bd86a01a76b5a0400000001"
|
||||
|
||||
assert.equal(str, correctStr)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toASM", () => {
|
||||
describe("P2PKH scriptSig", () => {
|
||||
fixtures.scriptSigToASM.forEach(fixture => {
|
||||
it(`should encode scriptSig buffer to ${fixture.asm}`, () => {
|
||||
const arr = [
|
||||
Buffer.from(fixture.scriptSigChunks[0], "hex"),
|
||||
Buffer.from(fixture.scriptSigChunks[1], "hex")
|
||||
]
|
||||
const compiledScriptSig = bchjs.Script.encode(arr)
|
||||
const asm = bchjs.Script.toASM(compiledScriptSig)
|
||||
assert.equal(asm, fixture.asm)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("P2PKH scriptPubKey", () => {
|
||||
fixtures.scriptPubKeyToASM.forEach(fixture => {
|
||||
it(`should compile scriptPubKey buffer to ${fixture.asm}`, () => {
|
||||
const asm = bchjs.Script.toASM(
|
||||
Buffer.from(fixture.scriptPubKeyHex, "hex")
|
||||
)
|
||||
assert.equal(asm, fixture.asm)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#fromASM", () => {
|
||||
describe("P2PKH scriptSig", () => {
|
||||
fixtures.scriptSigFromASM.forEach(fixture => {
|
||||
it(`should decode scriptSig asm to buffer`, () => {
|
||||
const buf = bchjs.Script.fromASM(fixture.asm)
|
||||
assert.equal(typeof buf, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("P2PKH scriptPubKey", () => {
|
||||
fixtures.scriptPubKeyFromASM.forEach(fixture => {
|
||||
it(`should decode scriptPubKey asm to buffer`, () => {
|
||||
const buf = bchjs.Script.fromASM(fixture.asm)
|
||||
assert.equal(typeof buf, "object")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#OPCodes", () => {
|
||||
for (const opcode in fixtures.opcodes) {
|
||||
it(`should have OP Code ${opcode}`, () => {
|
||||
assert.equal(bchjs.Script.opcodes[opcode], fixtures.opcodes[opcode])
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe("#classifyInput", () => {
|
||||
fixtures.classifyInput.forEach(fixture => {
|
||||
it(`should classify input type ${fixture.type}`, () => {
|
||||
const type = bchjs.Script.classifyInput(
|
||||
bchjs.Script.fromASM(fixture.script)
|
||||
)
|
||||
assert.equal(type, fixture.type)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#classifyOutput", () => {
|
||||
fixtures.classifyOutput.forEach(fixture => {
|
||||
it(`should classify ouput type ${fixture.type}`, () => {
|
||||
const type = bchjs.Script.classifyOutput(
|
||||
bchjs.Script.fromASM(fixture.script)
|
||||
)
|
||||
assert.equal(type, fixture.type)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#nullDataTemplate", () => {
|
||||
fixtures.nullDataTemplate.forEach(fixture => {
|
||||
it(`should encode nulldata output`, () => {
|
||||
const buf = bchjs.Script.nullData.output.encode(
|
||||
Buffer.from(`${fixture.data}`, "ascii")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode nulldata output`, () => {
|
||||
const buf = bchjs.Script.nullData.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("ascii"), fixture.data)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted nulldata output`, () => {
|
||||
const buf = bchjs.Script.nullData.output.encode(
|
||||
Buffer.from(`${fixture.data}`, "ascii")
|
||||
)
|
||||
const valid = bchjs.Script.nullData.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#pubKeyTemplate", () => {
|
||||
describe("#pubKeyInputTemplate", () => {
|
||||
fixtures.pubKeyInputTemplate.forEach(fixture => {
|
||||
it(`should encode pubKey input`, () => {
|
||||
const buf = bchjs.Script.pubKey.input.encode(
|
||||
Buffer.from(fixture.signature, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode pubKey input`, () => {
|
||||
const buf = bchjs.Script.pubKey.input.decode(
|
||||
Buffer.from(fixture.hex, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.signature)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted pubKeyHash input`, () => {
|
||||
const buf = bchjs.Script.pubKey.input.encode(
|
||||
Buffer.from(fixture.signature, "hex")
|
||||
)
|
||||
const valid = bchjs.Script.pubKey.input.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#pubKeyOutputTemplate", () => {
|
||||
fixtures.pubKeyOutputTemplate.forEach(fixture => {
|
||||
it(`should encode pubKey output`, () => {
|
||||
const buf = bchjs.Script.pubKey.output.encode(
|
||||
Buffer.from(fixture.pubKey, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode pubKey output`, () => {
|
||||
const buf = bchjs.Script.pubKey.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.pubKey)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted pubKey output`, () => {
|
||||
const buf = bchjs.Script.pubKey.output.encode(
|
||||
Buffer.from(fixture.pubKey, "hex")
|
||||
)
|
||||
const valid = bchjs.Script.pubKey.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#pubKeyHashTemplate", () => {
|
||||
describe("#pubKeyHashInputTemplate", () => {
|
||||
fixtures.pubKeyHashInputTemplate.forEach(fixture => {
|
||||
it(`should encode pubKeyHash input`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.input.encode(
|
||||
Buffer.from(fixture.signature, "hex"),
|
||||
Buffer.from(fixture.pubKey, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode pubKeyHash input signature`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.input.decode(
|
||||
Buffer.from(fixture.hex, "hex")
|
||||
)
|
||||
assert.equal(buf.signature.toString("hex"), fixture.signature)
|
||||
})
|
||||
|
||||
it(`should decode pubKeyHash input pubkey`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.input.decode(
|
||||
Buffer.from(fixture.hex, "hex")
|
||||
)
|
||||
assert.equal(buf.pubKey.toString("hex"), fixture.pubKey)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted pubKeyHash input`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.input.encode(
|
||||
Buffer.from(fixture.signature, "hex"),
|
||||
Buffer.from(fixture.pubKey, "hex")
|
||||
)
|
||||
const valid = bchjs.Script.pubKeyHash.input.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#pubKeyHashOutputTemplate", () => {
|
||||
fixtures.pubKeyHashOutputTemplate.forEach(fixture => {
|
||||
const node = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
const identifier = bchjs.HDNode.toIdentifier(node)
|
||||
it(`should encode pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.encode(identifier)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), identifier.toString("hex"))
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.encode(identifier)
|
||||
const valid = bchjs.Script.pubKeyHash.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#multisigTemplate", () => {
|
||||
describe("#multisigInputTemplate", () => {
|
||||
fixtures.multisigInputTemplate.forEach(fixture => {
|
||||
it(`should encode multisig input`, () => {
|
||||
const signatures = fixture.signatures.map(signature =>
|
||||
signature
|
||||
? Buffer.from(signature, "hex")
|
||||
: bchjs.Script.opcodes.OP_0
|
||||
)
|
||||
|
||||
const buf = bchjs.Script.multisig.input.encode(signatures)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode multisig input`, () => {
|
||||
const buf = bchjs.Script.multisig.input.decode(
|
||||
Buffer.from(fixture.hex, "hex")
|
||||
)
|
||||
assert.equal(buf[0].toString("hex"), fixture.signatures[0])
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted multisig input`, () => {
|
||||
const signatures = fixture.signatures.map(signature =>
|
||||
signature
|
||||
? Buffer.from(signature, "hex")
|
||||
: bchjs.Script.opcodes.OP_0
|
||||
)
|
||||
|
||||
const buf = bchjs.Script.multisig.input.encode(signatures)
|
||||
const valid = bchjs.Script.multisig.input.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#multisigOutputTemplate", () => {
|
||||
fixtures.multisigOutputTemplate.forEach(fixture => {
|
||||
it(`should encode multisig output`, () => {
|
||||
const pubKeys = fixture.pubKeys.map(p => Buffer.from(p, "hex"))
|
||||
const m = pubKeys.length
|
||||
const buf = bchjs.Script.multisig.output.encode(m, pubKeys)
|
||||
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode multisig output`, () => {
|
||||
const output = bchjs.Script.multisig.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.equal(output.m, fixture.pubKeys.length)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted multisig output`, () => {
|
||||
const pubKeys = fixture.pubKeys.map(p => Buffer.from(p, "hex"))
|
||||
const m = pubKeys.length
|
||||
const buf = bchjs.Script.multisig.output.encode(m, pubKeys)
|
||||
const valid = bchjs.Script.multisig.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#scriptHashTemplate", () => {
|
||||
describe("#scriptHashInputTemplate", () => {
|
||||
fixtures.scriptHashInputTemplate.forEach(fixture => {
|
||||
it(`should encode scriptHash input`, () => {
|
||||
const buf = bchjs.Script.scriptHash.input.encode(
|
||||
bchjs.Script.fromASM(fixture.redeemScriptSig),
|
||||
bchjs.Script.fromASM(fixture.redeemScript)
|
||||
)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode scriptHash input`, () => {
|
||||
const redeemScriptSig = bchjs.Script.fromASM(fixture.redeemScriptSig)
|
||||
const redeemScript = bchjs.Script.fromASM(fixture.redeemScript)
|
||||
assert.deepEqual(
|
||||
bchjs.Script.scriptHash.input.decode(
|
||||
Buffer.from(fixture.hex, "hex")
|
||||
),
|
||||
{
|
||||
redeemScriptSig: redeemScriptSig,
|
||||
redeemScript: redeemScript
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted scriptHash input`, () => {
|
||||
const buf = bchjs.Script.scriptHash.input.encode(
|
||||
bchjs.Script.fromASM(fixture.redeemScriptSig),
|
||||
bchjs.Script.fromASM(fixture.redeemScript)
|
||||
)
|
||||
const valid = bchjs.Script.scriptHash.input.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#scriptHashOutputTemplate", () => {
|
||||
fixtures.scriptHashOutputTemplate.forEach(fixture => {
|
||||
it(`should encode scriptHash output`, () => {
|
||||
const redeemScript = bchjs.Script.fromASM(fixture.output)
|
||||
const scriptHash = bchjs.Crypto.hash160(redeemScript)
|
||||
const buf = bchjs.Script.scriptHash.output.encode(scriptHash)
|
||||
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode scriptHash output`, () => {
|
||||
const redeemScript = bchjs.Script.fromASM(fixture.output)
|
||||
const scriptHash = bchjs.Crypto.hash160(redeemScript)
|
||||
const buf = bchjs.Script.scriptHash.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.deepEqual(buf, scriptHash)
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted scriptHash output`, () => {
|
||||
const redeemScript = bchjs.Script.fromASM(fixture.output)
|
||||
const scriptHash = bchjs.Crypto.hash160(redeemScript)
|
||||
const buf = bchjs.Script.scriptHash.output.encode(scriptHash)
|
||||
const valid = bchjs.Script.scriptHash.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,838 +0,0 @@
|
||||
const assert = require("assert")
|
||||
|
||||
const slp = require("../../src/slp/slp")
|
||||
const SLP = new slp({ restURL: "http://fakeurl.com/" })
|
||||
|
||||
const fixtures = require("./fixtures/slp/address.json")
|
||||
//const axios = require("axios")
|
||||
//const sinon = require("sinon")
|
||||
|
||||
function flatten(arrays) {
|
||||
return [].concat.apply([], arrays)
|
||||
}
|
||||
|
||||
const LEGACY_MAINNET_ADDRESSES = flatten([
|
||||
fixtures.mainnet.legacyP2PKH,
|
||||
fixtures.mainnet.legacyP2SH
|
||||
])
|
||||
|
||||
const CASH_MAINNET_ADDRESSES = flatten([
|
||||
fixtures.mainnet.cashAddressP2PKH,
|
||||
fixtures.mainnet.cashAddressP2SH
|
||||
])
|
||||
|
||||
const SLP_MAINNET_ADDRESSES = flatten([
|
||||
fixtures.mainnet.slpAddressP2PKH,
|
||||
fixtures.mainnet.slpAddressP2SH
|
||||
])
|
||||
|
||||
const LEGACY_TESTNET_ADDRESSES = flatten([
|
||||
fixtures.testnet.legacyP2PKH,
|
||||
fixtures.testnet.legacyP2SH
|
||||
])
|
||||
|
||||
const CASH_TESTNET_ADDRESSES = flatten([
|
||||
fixtures.testnet.cashAddressP2PKH,
|
||||
fixtures.testnet.cashAddressP2SH
|
||||
])
|
||||
|
||||
const SLP_TESTNET_ADDRESSES = flatten([
|
||||
fixtures.testnet.slpAddressP2PKH,
|
||||
fixtures.testnet.slpAddressP2SH
|
||||
])
|
||||
|
||||
const MAINNET_P2PKH_ADDRESSES = flatten([
|
||||
fixtures.mainnet.legacyP2PKH,
|
||||
fixtures.mainnet.cashAddressP2PKH,
|
||||
fixtures.mainnet.slpAddressP2PKH
|
||||
])
|
||||
|
||||
const TESTNET_P2PKH_ADDRESSES = flatten([
|
||||
fixtures.testnet.legacyP2PKH,
|
||||
fixtures.testnet.cashAddressP2PKH,
|
||||
fixtures.testnet.slpAddressP2PKH
|
||||
])
|
||||
|
||||
const MAINNET_P2SH_ADDRESSES = flatten([
|
||||
fixtures.mainnet.legacyP2SH,
|
||||
fixtures.mainnet.cashAddressP2SH,
|
||||
fixtures.mainnet.slpAddressP2SH
|
||||
])
|
||||
|
||||
const TESTNET_P2SH_ADDRESSES = flatten([
|
||||
fixtures.testnet.legacyP2SH,
|
||||
fixtures.testnet.cashAddressP2SH,
|
||||
fixtures.testnet.slpAddressP2SH
|
||||
])
|
||||
/*
|
||||
const CASH_MAINNET_ADDRESSES_NO_PREFIX = CASH_MAINNET_ADDRESSES.map(address => {
|
||||
const parts = address.split(":")
|
||||
return parts[1]
|
||||
})
|
||||
|
||||
const CASH_TESTNET_ADDRESSES_NO_PREFIX = CASH_TESTNET_ADDRESSES.map(address => {
|
||||
const parts = address.split(":")
|
||||
return parts[1]
|
||||
})
|
||||
|
||||
const SLP_MAINNET_ADDRESSES_NO_PREFIX = SLP_MAINNET_ADDRESSES.map(address => {
|
||||
const parts = address.split(":")
|
||||
return parts[1]
|
||||
})
|
||||
|
||||
const SLP_TESTNET_ADDRESSES_NO_PREFIX = SLP_TESTNET_ADDRESSES.map(address => {
|
||||
const parts = address.split(":")
|
||||
return parts[1]
|
||||
})
|
||||
*/
|
||||
describe("#SLP Address", () => {
|
||||
describe("#mainnet", () => {
|
||||
describe("#toLegacyAddress", () => {
|
||||
it("should convert mainnet legacy address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert cashAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert slpAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toCashAddress", () => {
|
||||
it("should convert mainnet cash address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
CASH_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert legacyAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert slpAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toSLPAddress", () => {
|
||||
it("should convert mainnet slp address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
SLP_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert legacyAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert cashAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_MAINNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_MAINNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isLegacyAddress", () => {
|
||||
describe("is legacy addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("cashaddr is not legacy addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("slpaddr is not legacy addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isCashAddress", () => {
|
||||
describe("is cashaddr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cashaddr address`, () => {
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("legacy is not cash addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("slpaddr is not cash addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isSLPAddress", () => {
|
||||
describe("is slpaddr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("legacy is not slp addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("cash is not slp addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isMainnetAddress", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("mainnet cash addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("mainnet slp addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("testnet legacy addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a mainnet address`, () => {
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("testnet cash addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a mainnet address`, () => {
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("testnet slp addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a mainnet address`, () => {
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isP2PKHAddress", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
MAINNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2PKH address`, () => {
|
||||
const isP2PKHaddr = SLP.Address.isP2PKHAddress(address)
|
||||
assert.equal(isP2PKHaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isP2SHAddress", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
MAINNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2SH address`, () => {
|
||||
const isP2SHaddr = SLP.Address.isP2SHAddress(address)
|
||||
assert.equal(isP2SHaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressFormat", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacy = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isLegacy, "legacy")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cash address`, () => {
|
||||
const isCashaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isCashaddr, "cashaddr")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSlpaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isSlpaddr, "slpaddr")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressNetwork", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isMainnet, "mainnet")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isMainnet, "mainnet")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isMainnet, "mainnet")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressType", () => {
|
||||
MAINNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2pkh address`, () => {
|
||||
const isp2pkh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2pkh, "p2pkh")
|
||||
})
|
||||
})
|
||||
|
||||
MAINNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2sh address`, () => {
|
||||
const isp2sh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2sh, "p2sh")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#testnet", () => {
|
||||
describe("#toLegacyAddress", () => {
|
||||
it("should convert testnet legacy address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert cashAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert slpAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toCashAddress", () => {
|
||||
it("should convert testnet cash address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
CASH_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert legacyAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert slpAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#toSLPAddress", () => {
|
||||
it("should convert testnet slp address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
SLP_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert legacyAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
|
||||
it(`should convert cashAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_TESTNET_ADDRESSES.map(address =>
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_TESTNET_ADDRESSES
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isLegacyAddress", () => {
|
||||
describe("is legacy addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("cashaddr is not legacy addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("slpaddr is not legacy addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isCashAddress", () => {
|
||||
describe("is cashaddr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cashaddr address`, () => {
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("legacy is not cash addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("slpaddr is not cash addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isSLPAddress", () => {
|
||||
describe("is slpaddr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("legacy is not slp addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("cash is not slp addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isTestnetAddress", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("testnet cash addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("testnet slp addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("mainnet legacy addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a testnet address`, () => {
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("mainnet cash addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a testnet address`, () => {
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("mainnet slp addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a testnet address`, () => {
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isP2PKHAddress", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
TESTNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2PKH address`, () => {
|
||||
const isP2PKHaddr = SLP.Address.isP2PKHAddress(address)
|
||||
assert.equal(isP2PKHaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#isP2SHAddress", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
TESTNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2SH address`, () => {
|
||||
const isP2SHaddr = SLP.Address.isP2SHAddress(address)
|
||||
assert.equal(isP2SHaddr, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressFormat", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacy = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isLegacy, "legacy")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cash address`, () => {
|
||||
const isCashaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isCashaddr, "cashaddr")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSlpaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isSlpaddr, "slpaddr")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressNetwork", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isTestnet, "testnet")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isTestnet, "testnet")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isTestnet, "testnet")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressType", () => {
|
||||
TESTNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2pkh address`, () => {
|
||||
const isp2pkh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2pkh, "p2pkh")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#detectAddressType", () => {
|
||||
TESTNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2sh address`, () => {
|
||||
const isp2sh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2sh, "p2sh")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
/*
|
||||
describe("#details", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.sandbox.create()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get details", done => {
|
||||
const data = {
|
||||
balance: 0.00000546,
|
||||
balanceSat: 546,
|
||||
totalReceived: 0.00426132,
|
||||
totalReceivedSat: 426132,
|
||||
totalSent: 0.00425586,
|
||||
totalSentSat: 425586,
|
||||
unconfirmedBalance: 0,
|
||||
unconfirmedBalanceSat: 0,
|
||||
unconfirmedTxApperances: 0,
|
||||
txApperances: 3,
|
||||
transactions: [
|
||||
"902fe6ed7a19570c032b3ba4c4d7af92804662b486a15c8ca2d284166c658dd4",
|
||||
"467969e067f5612863d0bf2daaa70dede2c6be03abb6fd401c5ef6e1e1f1f5c5",
|
||||
"c1d9f3490e96a1fe4f77195067f1ab12c787f79b39d107424e0c4c810098e11b"
|
||||
],
|
||||
legacyAddress: "1NM2ozrXVSnMRm66ua6aGeXgMsU7yqwqLS",
|
||||
cashAddress: "bitcoincash:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3g4hl47n9y",
|
||||
slpAddress: "simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6",
|
||||
currentPage: 0,
|
||||
pagesTotal: 1
|
||||
}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
SLP.Address.details(
|
||||
"simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6"
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#utxo", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.sandbox.create()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get utxo", done => {
|
||||
const data = {
|
||||
utxos: [
|
||||
{
|
||||
txid:
|
||||
"467969e067f5612863d0bf2daaa70dede2c6be03abb6fd401c5ef6e1e1f1f5c5",
|
||||
vout: 1,
|
||||
amount: 0.00000546,
|
||||
satoshis: 546,
|
||||
height: 568215,
|
||||
confirmations: 24
|
||||
}
|
||||
],
|
||||
legacyAddress: "1NM2ozrXVSnMRm66ua6aGeXgMsU7yqwqLS",
|
||||
cashAddress: "bitcoincash:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3g4hl47n9y",
|
||||
scriptPubKey: "76a914ea2478cbb9f44100b547cf264d34155dce044b8a88ac"
|
||||
}
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
SLP.Address.utxo("simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6")
|
||||
.then(result => {
|
||||
assert.deepEqual(
|
||||
"467969e067f5612863d0bf2daaa70dede2c6be03abb6fd401c5ef6e1e1f1f5c5",
|
||||
result.utxos[0].txid
|
||||
)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#unconfirmed", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.sandbox.create()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should get unconfirmed transactions", done => {
|
||||
const data = {
|
||||
utxos: [],
|
||||
legacyAddress: "1NM2ozrXVSnMRm66ua6aGeXgMsU7yqwqLS",
|
||||
cashAddress: "bitcoincash:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3g4hl47n9y",
|
||||
slpAddress: "simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6",
|
||||
scriptPubKey: "76a914ea2478cbb9f44100b547cf264d34155dce044b8a88ac"
|
||||
}
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
SLP.Address.unconfirmed(
|
||||
"simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6"
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
*/
|
||||
|
||||
// (async () => {
|
||||
// try {
|
||||
// const details = await SLP.Address.unconfirmed(
|
||||
// "simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6"
|
||||
// )
|
||||
// console.log(details)
|
||||
// } catch (error) {
|
||||
// console.error(error)
|
||||
// }
|
||||
// })()
|
||||
@@ -1,17 +0,0 @@
|
||||
const fixtures = require("./fixtures/slp/ecpair.json")
|
||||
const assert = require("assert")
|
||||
|
||||
const SLP = require("../../src/slp/slp")
|
||||
const slp = new SLP({ restURL: "http://fakeurl.com/" })
|
||||
|
||||
describe("#SLP ECPair", () => {
|
||||
describe("#toSLPAddress", () => {
|
||||
it(`should return slp address for ecpair`, async () => {
|
||||
fixtures.wif.forEach((wif, index) => {
|
||||
const ecpair = slp.ECPair.fromWIF(wif)
|
||||
const slpAddr = slp.ECPair.toSLPAddress(ecpair)
|
||||
assert.equal(slpAddr, fixtures.address[index])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,264 +0,0 @@
|
||||
/*
|
||||
Unit tests for the TokenType1 library.
|
||||
*/
|
||||
|
||||
const assert = require("chai").assert
|
||||
const nock = require("nock") // http call mocking
|
||||
const sinon = require("sinon")
|
||||
// const axios = require("axios")
|
||||
|
||||
// Default to unit tests unless some other value for TEST is passed.
|
||||
if (!process.env.TEST) process.env.TEST = "unit"
|
||||
// const SERVER = bchjs.restURL
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
// Mock data used for unit tests
|
||||
// const mockData = require("./fixtures/slp/mock-utils")
|
||||
|
||||
// Default to unit tests unless some other value for TEST is passed.
|
||||
if (!process.env.TEST) process.env.TEST = "unit"
|
||||
|
||||
describe("#SLP NFT1", () => {
|
||||
let sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
// Activate nock if it's inactive.
|
||||
if (!nock.isActive()) nock.activate()
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
// Clean up HTTP mocks.
|
||||
nock.cleanAll() // clear interceptor list.
|
||||
nock.restore()
|
||||
|
||||
sandbox.restore()
|
||||
})
|
||||
|
||||
describe("#newNFTGroupOpReturn", () => {
|
||||
it("should generate new NFT Group OP_RETURN code", () => {
|
||||
const configObj = {
|
||||
name: "SLP Test Token",
|
||||
ticker: "SLPTEST",
|
||||
documentUrl: "https://bchjs.cash",
|
||||
documentHash: "",
|
||||
initialQty: 5
|
||||
}
|
||||
|
||||
const result = bchjs.SLP.NFT1.newNFTGroupOpReturn(configObj)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#mintNFTGroupOpReturn", () => {
|
||||
it("should generate NFT Group Mint OP_RETURN code", () => {
|
||||
const tokenUtxoData = [
|
||||
{
|
||||
txid:
|
||||
"3de3766b10506c9156533f1639979e49d1884521543c13e4af73647df1ed3f76",
|
||||
vout: 2,
|
||||
value: "546",
|
||||
height: 638207,
|
||||
confirmations: 63,
|
||||
satoshis: 546,
|
||||
utxoType: "minting-baton",
|
||||
transactionType: "mint",
|
||||
tokenId:
|
||||
"680967b3f6fe080dbca8dbd370665bd29742e3490db24e2f28d08b424511807e",
|
||||
tokenType: 129,
|
||||
tokenTicker: "NFTP",
|
||||
tokenName: "NFT Parent",
|
||||
tokenDocumentUrl: "FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 0,
|
||||
mintBatonVout: 2,
|
||||
isValid: true
|
||||
},
|
||||
{
|
||||
txid:
|
||||
"3de3766b10506c9156533f1639979e49d1884521543c13e4af73647df1ed3f76",
|
||||
vout: 1,
|
||||
value: "546",
|
||||
height: 638207,
|
||||
confirmations: 63,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
tokenQty: 10,
|
||||
transactionType: "mint",
|
||||
tokenId:
|
||||
"680967b3f6fe080dbca8dbd370665bd29742e3490db24e2f28d08b424511807e",
|
||||
tokenType: 129,
|
||||
tokenTicker: "NFTP",
|
||||
tokenName: "NFT Parent",
|
||||
tokenDocumentUrl: "FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 0,
|
||||
mintBatonVout: 2,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.NFT1.mintNFTGroupOpReturn(tokenUtxoData, 10)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#generateNFTChildOpReturn", () => {
|
||||
it("should generate NFT Genesis OP_RETURN code", () => {
|
||||
const configObj = {
|
||||
name: "SLP Test Token",
|
||||
ticker: "SLPTEST",
|
||||
documentUrl: "https://bchjs.cash",
|
||||
documentHash: ""
|
||||
}
|
||||
|
||||
const result = bchjs.SLP.NFT1.generateNFTChildGenesisOpReturn(configObj)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#generateNFTChildSendOpReturn", () => {
|
||||
it("should generate send OP_RETURN code for no change", () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
txid:
|
||||
"81955624a8eb7011769ff5faa607f78f84b0f8152b9145e7db8b1e521c895ee3",
|
||||
vout: 1,
|
||||
value: "546",
|
||||
height: 638273,
|
||||
confirmations: 42,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
tokenQty: 1,
|
||||
tokenId:
|
||||
"81955624a8eb7011769ff5faa607f78f84b0f8152b9145e7db8b1e521c895ee3",
|
||||
tokenTicker: "NFTC",
|
||||
tokenName: "NFT Child",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 0,
|
||||
tokenType: 129,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.NFT1.generateNFTChildSendOpReturn(tokenUtxos, 1)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, ["script", "outputs"])
|
||||
assert.isNumber(result.outputs)
|
||||
})
|
||||
|
||||
it("should generate send OP_RETURN code with change", () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
txid:
|
||||
"81955624a8eb7011769ff5faa607f78f84b0f8152b9145e7db8b1e521c895ee3",
|
||||
vout: 1,
|
||||
value: "546",
|
||||
height: 638273,
|
||||
confirmations: 42,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
tokenQty: 4,
|
||||
tokenId:
|
||||
"81955624a8eb7011769ff5faa607f78f84b0f8152b9145e7db8b1e521c895ee3",
|
||||
tokenTicker: "NFTC",
|
||||
tokenName: "NFT Child",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 0,
|
||||
tokenType: 129,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.NFT1.generateNFTChildSendOpReturn(tokenUtxos, 1)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, ["script", "outputs"])
|
||||
assert.isNumber(result.outputs)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#generateNFTGroupSendOpReturn", () => {
|
||||
it("should generate send OP_RETURN with change", () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
txid:
|
||||
"35846676e7514658bbd2fd60b1f0d4d86195908f6b2de5328d54c8e4a2d05919",
|
||||
vout: 1,
|
||||
value: "546",
|
||||
height: 638207,
|
||||
confirmations: 3,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
tokenQty: 10,
|
||||
transactionType: "mint",
|
||||
tokenId:
|
||||
"eee4b82e4bb7113eca433829144363fc45f110693c286494fbf5b5c8043cc981",
|
||||
tokenType: 129,
|
||||
tokenTicker: "NFTTT",
|
||||
tokenName: "NFT Test Token",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 0,
|
||||
mintBatonVout: 2,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.NFT1.generateNFTGroupSendOpReturn(tokenUtxos, 1)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, ["script", "outputs"])
|
||||
assert.isNumber(result.outputs)
|
||||
})
|
||||
|
||||
it("should generate send OP_RETURN with no change", () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
txid:
|
||||
"35846676e7514658bbd2fd60b1f0d4d86195908f6b2de5328d54c8e4a2d05919",
|
||||
vout: 1,
|
||||
value: "546",
|
||||
height: 638207,
|
||||
confirmations: 3,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
tokenQty: 10,
|
||||
transactionType: "mint",
|
||||
tokenId:
|
||||
"eee4b82e4bb7113eca433829144363fc45f110693c286494fbf5b5c8043cc981",
|
||||
tokenType: 129,
|
||||
tokenTicker: "NFTTT",
|
||||
tokenName: "NFT Test Token",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 0,
|
||||
mintBatonVout: 2,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.NFT1.generateNFTGroupSendOpReturn(tokenUtxos, 10)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, ["script", "outputs"])
|
||||
assert.isNumber(result.outputs)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
Unit tests for the TokenType1 library.
|
||||
*/
|
||||
|
||||
const assert = require("chai").assert
|
||||
const nock = require("nock") // http call mocking
|
||||
const sinon = require("sinon")
|
||||
// const axios = require("axios")
|
||||
|
||||
// Default to unit tests unless some other value for TEST is passed.
|
||||
if (!process.env.TEST) process.env.TEST = "unit"
|
||||
// const SERVER = bchjs.restURL
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
// Mock data used for unit tests
|
||||
// const mockData = require("./fixtures/slp/mock-utils")
|
||||
|
||||
// Default to unit tests unless some other value for TEST is passed.
|
||||
if (!process.env.TEST) process.env.TEST = "unit"
|
||||
|
||||
describe("#SLP TokenType1", () => {
|
||||
let sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
// Activate nock if it's inactive.
|
||||
if (!nock.isActive()) nock.activate()
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
// Clean up HTTP mocks.
|
||||
nock.cleanAll() // clear interceptor list.
|
||||
nock.restore()
|
||||
|
||||
sandbox.restore()
|
||||
})
|
||||
|
||||
describe("#generateSendOpReturn", () => {
|
||||
it("should generate send OP_RETURN code", () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
txid:
|
||||
"a8eb788b8ddda6faea00e6e2756624b8feb97655363d0400dd66839ea619d36e",
|
||||
vout: 2,
|
||||
value: "546",
|
||||
confirmations: 0,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
transactionType: "send",
|
||||
tokenId:
|
||||
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7",
|
||||
tokenTicker: "TOK-CH",
|
||||
tokenName: "TokyoCash",
|
||||
tokenDocumentUrl: "",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 8,
|
||||
tokenQty: 7
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateSendOpReturn(tokenUtxos, 1)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, ["script", "outputs"])
|
||||
assert.isNumber(result.outputs)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#generateBurnOpReturn", () => {
|
||||
it("should generate burn OP_RETURN code", () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
txid:
|
||||
"a8eb788b8ddda6faea00e6e2756624b8feb97655363d0400dd66839ea619d36e",
|
||||
vout: 2,
|
||||
value: "546",
|
||||
confirmations: 0,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
transactionType: "send",
|
||||
tokenId:
|
||||
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7",
|
||||
tokenTicker: "TOK-CH",
|
||||
tokenName: "TokyoCash",
|
||||
tokenDocumentUrl: "",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 8,
|
||||
tokenQty: 7
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateBurnOpReturn(tokenUtxos, 1)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#generateGenesisOpReturn", () => {
|
||||
it("should generate genesis OP_RETURN code", () => {
|
||||
const configObj = {
|
||||
name: "SLP Test Token",
|
||||
ticker: "SLPTEST",
|
||||
documentUrl: "https://bchjs.cash",
|
||||
documentHash: "",
|
||||
decimals: 8,
|
||||
initialQty: 10
|
||||
}
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateGenesisOpReturn(configObj)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
|
||||
it("should work if user does not specify doc hash", () => {
|
||||
const configObj = {
|
||||
name: "SLP Test Token",
|
||||
ticker: "SLPTEST",
|
||||
documentUrl: "https://bchjs.cash",
|
||||
decimals: 8,
|
||||
initialQty: 10
|
||||
}
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateGenesisOpReturn(configObj)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#generateMintOpReturn", () => {
|
||||
it("should throw error if tokenUtxos is not an array.", () => {
|
||||
try {
|
||||
bchjs.SLP.TokenType1.generateMintOpReturn({}, 100)
|
||||
|
||||
assert.equal(true, false, "Unexpected result.")
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
`tokenUtxos must be an array`,
|
||||
"Expected error message."
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw error if minting baton is not in UTXOs.", () => {
|
||||
try {
|
||||
const utxos = [
|
||||
{
|
||||
txid:
|
||||
"ccc6d336399e26d98afcd3821b41fb1535cd50f57063ed7593eaed5108659606",
|
||||
vout: 1,
|
||||
value: "546",
|
||||
height: 637618,
|
||||
confirmations: 239,
|
||||
satoshis: 546,
|
||||
utxoType: "token",
|
||||
tokenQty: 100,
|
||||
tokenId:
|
||||
"ccc6d336399e26d98afcd3821b41fb1535cd50f57063ed7593eaed5108659606",
|
||||
tokenTicker: "SLPTEST",
|
||||
tokenName: "SLP Test Token",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 8,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
bchjs.SLP.TokenType1.generateMintOpReturn(utxos, 100)
|
||||
|
||||
assert.equal(true, false, "Unexpected result.")
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
`Minting baton could not be found in tokenUtxos array`,
|
||||
"Expected error message."
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw error if tokenId is not included in minting-baton UTXO.", () => {
|
||||
try {
|
||||
const utxos = [
|
||||
{
|
||||
txid:
|
||||
"9d35c1803ed3ab8bd23c198b027f7b3b530586494dc265de6391b74a6b090136",
|
||||
vout: 2,
|
||||
value: "546",
|
||||
height: 637625,
|
||||
confirmations: 207,
|
||||
satoshis: 546,
|
||||
utxoType: "minting-baton",
|
||||
tokenTicker: "SLPTEST",
|
||||
tokenName: "SLP Test Token",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 8,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
bchjs.SLP.TokenType1.generateMintOpReturn(utxos, 100)
|
||||
|
||||
assert.equal(true, false, "Unexpected result.")
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
`tokenId property not found in mint-baton UTXO`,
|
||||
"Expected error message."
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should throw error if decimals is not included in minting-baton UTXO.", () => {
|
||||
try {
|
||||
const utxos = [
|
||||
{
|
||||
txid:
|
||||
"9d35c1803ed3ab8bd23c198b027f7b3b530586494dc265de6391b74a6b090136",
|
||||
vout: 2,
|
||||
value: "546",
|
||||
height: 637625,
|
||||
confirmations: 207,
|
||||
satoshis: 546,
|
||||
utxoType: "minting-baton",
|
||||
tokenId:
|
||||
"9d35c1803ed3ab8bd23c198b027f7b3b530586494dc265de6391b74a6b090136",
|
||||
tokenTicker: "SLPTEST",
|
||||
tokenName: "SLP Test Token",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
bchjs.SLP.TokenType1.generateMintOpReturn(utxos, 100)
|
||||
|
||||
assert.equal(true, false, "Unexpected result.")
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
`decimals property not found in mint-baton UTXO`,
|
||||
"Expected error message."
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("should generate genesis OP_RETURN code", () => {
|
||||
tokenUtxo = [
|
||||
{
|
||||
txid:
|
||||
"9d35c1803ed3ab8bd23c198b027f7b3b530586494dc265de6391b74a6b090136",
|
||||
vout: 2,
|
||||
value: "546",
|
||||
height: 637625,
|
||||
confirmations: 207,
|
||||
satoshis: 546,
|
||||
utxoType: "minting-baton",
|
||||
tokenId:
|
||||
"9d35c1803ed3ab8bd23c198b027f7b3b530586494dc265de6391b74a6b090136",
|
||||
tokenTicker: "SLPTEST",
|
||||
tokenName: "SLP Test Token",
|
||||
tokenDocumentUrl: "https://FullStack.cash",
|
||||
tokenDocumentHash: "",
|
||||
decimals: 8,
|
||||
isValid: true
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateMintOpReturn(tokenUtxo, 100)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
assert.equal(Buffer.isBuffer(result), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getHexOpReturn", () => {
|
||||
it("should return OP_RETURN object ", async () => {
|
||||
const tokenUtxos = [
|
||||
{
|
||||
tokenId:
|
||||
"0a321bff9761f28e06a268b14711274bb77617410a16807bd0437ef234a072b1",
|
||||
decimals: 0,
|
||||
tokenQty: 2
|
||||
}
|
||||
]
|
||||
|
||||
const sendQty = 1.5
|
||||
|
||||
sandbox.stub(bchjs.SLP.TokenType1.axios, "post").resolves({
|
||||
data: {
|
||||
script:
|
||||
"6a04534c500001010453454e44200a321bff9761f28e06a268b14711274bb77617410a16807bd0437ef234a072b1080000000000000001080000000000000000",
|
||||
outputs: 2
|
||||
}
|
||||
})
|
||||
|
||||
const result = await bchjs.SLP.TokenType1.getHexOpReturn(
|
||||
tokenUtxos,
|
||||
sendQty
|
||||
)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "script")
|
||||
assert.isString(result.script)
|
||||
|
||||
assert.property(result, "outputs")
|
||||
assert.isNumber(result.outputs)
|
||||
})
|
||||
})
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
describe("#Util", () => {
|
||||
describe("#validateAddress", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
it("should validate address", done => {
|
||||
const data = {
|
||||
isvalid: true,
|
||||
address: "bitcoincash:qpz7qtkuyhrsz4qmnnrvf8gz9zd0u9v7eqsewyk4w5",
|
||||
scriptPubKey: "76a91445e02edc25c701541b9cc6c49d02289afe159ec888ac",
|
||||
ismine: false,
|
||||
iswatchonly: false,
|
||||
isscript: false
|
||||
}
|
||||
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
bchjs.Util.validateAddress(
|
||||
"bitcoincash:qpz7qtkuyhrsz4qmnnrvf8gz9zd0u9v7eqsewyk4w5"
|
||||
)
|
||||
.then(result => {
|
||||
assert.deepEqual(data, result)
|
||||
})
|
||||
.then(done, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user