mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-22 09:02:01 -07:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
278a54bd9b | ||
|
|
30b1f71d81 | ||
|
|
e7d7fc1019 | ||
|
|
524da532e2 | ||
|
|
e2ba265878 |
@@ -1,9 +1,9 @@
|
||||
# bch-js
|
||||
|
||||
[](https://travis-ci.org/Permissionless-Software-Foundation/bch-js)
|
||||
[](https://www.npmjs.com/package/@psf/bch-js)
|
||||
[](https://npmjs.org/package/@psf/bch-js)
|
||||
[](https://github.com/Permissionless-Software-Foundation/bch-js/blob/master/LICENSE.md)
|
||||
[](https://github.com/feross/standard)
|
||||
|
||||
[bch-js](https://www.npmjs.com/package/@psf/bch-js) is a JavaScript npm library for creating web and mobile apps that can interact with the Bitcoin Cash (BCH) blockchains. It can be used for free, but requires an account on [FullStack.cash](https://fullstack.cash) for increased rate limits. Learn more from [this article](https://troutsblog.com/research/bitcoin-cash/how-to-bch-full-stack-developer) about Full Stack Bitcoin Cash development.
|
||||
|
||||
@@ -117,7 +117,7 @@ Have questions? Need help? Join our community support
|
||||
|
||||
Copies of this repository are also published on [IPFS](https://ipfs.io).
|
||||
|
||||
- v3.8.10: QmauhggzKDo9A9je5y2K6WRAp32JmGRFCw2ZFTiSnW8yot
|
||||
- v4.5.4: QmWv3pxJy3MH8vU5nLUVyzqFxfNKXLQQEnz1rgStNuQijd
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+15
-7
@@ -33,22 +33,33 @@ const IPFS = require('./ipfs')
|
||||
const Encryption = require('./encryption')
|
||||
|
||||
// Indexers
|
||||
const OpenBazaar = require('./openbazaar')
|
||||
const Ninsight = require('./ninsight')
|
||||
const Electrumx = require('./electrumx')
|
||||
|
||||
class BCHJS {
|
||||
constructor (config) {
|
||||
// Try to retrieve the REST API URL from different sources.
|
||||
if (config && config.restURL && config.restURL !== '') { this.restURL = config.restURL } else if (process.env.RESTURL && process.env.RESTURL !== '') { this.restURL = process.env.RESTURL } else this.restURL = DEFAULT_REST_API
|
||||
if (config && config.restURL && config.restURL !== '') {
|
||||
this.restURL = config.restURL
|
||||
} else if (process.env.RESTURL && process.env.RESTURL !== '') {
|
||||
this.restURL = process.env.RESTURL
|
||||
} else this.restURL = DEFAULT_REST_API
|
||||
|
||||
// Retrieve the apiToken
|
||||
this.apiToken = '' // default value.
|
||||
if (config && config.apiToken && config.apiToken !== '') { this.apiToken = config.apiToken } else if (process.env.BCHJSTOKEN && process.env.BCHJSTOKEN !== '') { this.apiToken = process.env.BCHJSTOKEN }
|
||||
if (config && config.apiToken && config.apiToken !== '') {
|
||||
this.apiToken = config.apiToken
|
||||
} else if (process.env.BCHJSTOKEN && process.env.BCHJSTOKEN !== '') {
|
||||
this.apiToken = process.env.BCHJSTOKEN
|
||||
}
|
||||
|
||||
// Retrieve the Basic Authentication password.
|
||||
this.authPass = '' // default value.
|
||||
if (config && config.authPass && config.authPass !== '') { this.authPass = config.authPass } else if (process.env.BCHJSAUTHPASS && process.env.BCHJSAUTHPASS !== '') { this.authPass = process.env.BCHJSAUTHPASS }
|
||||
if (config && config.authPass && config.authPass !== '') {
|
||||
this.authPass = config.authPass
|
||||
} else if (process.env.BCHJSAUTHPASS && process.env.BCHJSAUTHPASS !== '') {
|
||||
this.authPass = process.env.BCHJSAUTHPASS
|
||||
}
|
||||
|
||||
// Generate a Basic Authentication token from an auth password
|
||||
this.authToken = ''
|
||||
@@ -68,9 +79,6 @@ class BCHJS {
|
||||
|
||||
// console.log(`apiToken: ${this.apiToken}`)
|
||||
|
||||
// Populate OpenBazaar endpoints
|
||||
this.OpenBazaar = new OpenBazaar(libConfig)
|
||||
|
||||
// Bitcoin.com Ninsight indexer
|
||||
this.Ninsight = new Ninsight(config)
|
||||
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
This library interacts with the public REST API endpoints that OpenBazaar
|
||||
provides for their application.
|
||||
*/
|
||||
|
||||
const axios = require('axios')
|
||||
|
||||
let _this
|
||||
|
||||
class OpenBazaar {
|
||||
constructor (config) {
|
||||
this.restURL = config.restURL
|
||||
this.apiToken = config.apiToken
|
||||
|
||||
// Add JWT token to the authorization header.
|
||||
this.axiosOptions = {
|
||||
headers: {
|
||||
authorization: `Token ${this.apiToken}`
|
||||
}
|
||||
}
|
||||
|
||||
_this = this
|
||||
}
|
||||
|
||||
/**
|
||||
* @api OpenBazaar.balance() balance()
|
||||
* @apiName OpenBazaar Balance
|
||||
* @apiGroup OpenBazaar
|
||||
* @apiDescription Return Balance about an address.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* (async () => {
|
||||
* try {
|
||||
* let balance = await bchjs.OpenBazaar.balance('bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9');
|
||||
* console.log(balance)
|
||||
* } catch(error) {
|
||||
* console.error(error)
|
||||
* }
|
||||
* })()
|
||||
*
|
||||
* {
|
||||
* page: 1,
|
||||
* totalPages: 1,
|
||||
* itemsOnPage: 1000,
|
||||
* addrStr: "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9",
|
||||
* balance: "0.00001",
|
||||
* totalReceived: "0.00001",
|
||||
* totalSent: "0",
|
||||
* unconfirmedBalance: "0",
|
||||
* unconfirmedTxApperances: 0,
|
||||
* txApperances: 1,
|
||||
* transactions: [
|
||||
* "2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7"
|
||||
* ]
|
||||
* }
|
||||
*
|
||||
*/
|
||||
async balance (address) {
|
||||
try {
|
||||
// Handle single address.
|
||||
if (typeof address === 'string') {
|
||||
let response
|
||||
if (process.env.NETWORK === 'testnet') {
|
||||
response = await axios.get(
|
||||
`https://tbch.blockbook.api.openbazaar.org/api/address/${address}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
} else {
|
||||
response = await axios.get(
|
||||
`https://bch.blockbook.api.openbazaar.org/api/address/${address}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
}
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error('Input address must be a string.')
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api OpenBazaar.utxo() utxo()
|
||||
* @apiName OpenBazaar Utxo
|
||||
* @apiGroup OpenBazaar
|
||||
* @apiDescription Return list of uxto for address.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* (async () => {
|
||||
* try {
|
||||
* let utxo = await bchjs.OpenBazaar.utxo('bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9');
|
||||
* console.log(utxo);
|
||||
* } catch(error) {
|
||||
* console.error(error)
|
||||
* }
|
||||
* })()
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* txid: "2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7",
|
||||
* vout: 0,
|
||||
* amount: "0.00001",
|
||||
* satoshis: 1000,
|
||||
* height: 602405,
|
||||
* confirmations: 11
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
async utxo (address) {
|
||||
try {
|
||||
// Handle single address.
|
||||
if (typeof address === 'string') {
|
||||
let response
|
||||
if (process.env.NETWORK === 'testnet') {
|
||||
response = await axios.get(
|
||||
`https://tbch.blockbook.api.openbazaar.org/api/utxo/${address}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
} else {
|
||||
response = await axios.get(
|
||||
`https://bch.blockbook.api.openbazaar.org/api/utxo/${address}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
}
|
||||
return response.data
|
||||
}
|
||||
throw new Error('Input address must be a string.')
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api OpenBazaar.tx() tx()
|
||||
* @apiName OpenBazaar Tx
|
||||
* @apiGroup OpenBazaar
|
||||
* @apiDescription Get details on a transaction.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* (async () => {
|
||||
* try {
|
||||
* let txDetails = await bchjs.OpenBazaar.tx(`2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7`);
|
||||
* console.log(txDetails);
|
||||
* } catch(error) {
|
||||
* console.error(error)
|
||||
* }
|
||||
* })()
|
||||
*
|
||||
*{
|
||||
* txid: "2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7",
|
||||
* version: 2,
|
||||
* vin: [
|
||||
* {
|
||||
* txid: "5f09d317e24c5d376f737a2711f3bd1d381abdb41743fff3819b4f76382e1eac",
|
||||
* vout: 1,
|
||||
* sequence: 4294967295,
|
||||
* n: 0,
|
||||
* scriptSig: {
|
||||
* hex:
|
||||
* "473044022000dd11c41a472f2e54348db996e60864d489429f12d1e044d49ff600b880c9590220715a926404bb0e2731a3795afb341ec1dad3f84ead7d27cd31fcc59abb14738c4121038476128287ac37c7a3cf7e8625fd5f024db1bc3d8e37395abe7bf42fda78d0d9"
|
||||
* },
|
||||
* addresses: ["bitcoincash:qqxy8hycqe89j7wa79gnggq6z3gaqu2uvqy26xehfe"],
|
||||
* value: "0.00047504"
|
||||
* }
|
||||
* ],
|
||||
* vout: [
|
||||
* {
|
||||
* value: "0.00001",
|
||||
* n: 0,
|
||||
* scriptPubKey: {
|
||||
* hex: "76a9142fe2c4c5ef359bb2fe1a849f891cecffbcfb4f7788ac",
|
||||
* addresses: ["bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"]
|
||||
* },
|
||||
* spent: false
|
||||
* },
|
||||
* {
|
||||
* value: "0.00046256",
|
||||
* n: 1,
|
||||
* scriptPubKey: {
|
||||
* hex: "76a9142dbf5e1804c39a497b908c876097d63210c8490288ac",
|
||||
* addresses: ["bitcoincash:qqkm7hscqnpe5jtmjzxgwcyh6ceppjzfqg3jdn422e"]
|
||||
* },
|
||||
* spent: false
|
||||
* }
|
||||
* ],
|
||||
* blockhash: "0000000000000000010903a1fc4274499037c9339be9ec7338ee980331c20ce5",
|
||||
* blockheight: 602405,
|
||||
* confirmations: 11,
|
||||
* blocktime: 1569792892,
|
||||
* valueOut: "0.00047256",
|
||||
* valueIn: "0.00047504",
|
||||
* fees: "0.00000248",
|
||||
* hex:
|
||||
* "0200000001ac1e2e38764f9b81f3ff4317b4bd1a381dbdf311277a736f375d4ce217d3095f010000006a473044022000dd11c41a472f2e54348db996e60864d489429f12d1e044d49ff600b880c9590220715a926404bb0e2731a3795afb341ec1dad3f84ead7d27cd31fcc59abb14738c4121038476128287ac37c7a3cf7e8625fd5f024db1bc3d8e37395abe7bf42fda78d0d9ffffffff02e8030000000000001976a9142fe2c4c5ef359bb2fe1a849f891cecffbcfb4f7788acb0b40000000000001976a9142dbf5e1804c39a497b908c876097d63210c8490288ac00000000"
|
||||
* }
|
||||
*
|
||||
*/
|
||||
async tx (txid) {
|
||||
try {
|
||||
// Handle single txid.
|
||||
if (typeof txid === 'string') {
|
||||
let response
|
||||
if (process.env.NETWORK === 'testnet') {
|
||||
response = await axios.get(
|
||||
`https://tbch.blockbook.api.openbazaar.org/api/tx/${txid}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
} else {
|
||||
response = await axios.get(
|
||||
`https://bch.blockbook.api.openbazaar.org/api/tx/${txid}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
}
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error('Input txid must be a string.')
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OpenBazaar
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
tests for OpenBazaar library.
|
||||
*/
|
||||
|
||||
const chai = require('chai')
|
||||
const assert = chai.assert
|
||||
const BCHJS = require('../../src/bch-js')
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
describe('#OpenBazaar', () => {
|
||||
beforeEach(async () => {
|
||||
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
|
||||
})
|
||||
|
||||
describe('#Balance', () => {
|
||||
it('should GET balance for a single address', async () => {
|
||||
const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
||||
|
||||
const result = await bchjs.OpenBazaar.balance(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, [
|
||||
'page',
|
||||
'totalPages',
|
||||
'itemsOnPage',
|
||||
'addrStr',
|
||||
'balance',
|
||||
'totalReceived',
|
||||
'totalSent',
|
||||
'unconfirmedBalance',
|
||||
'unconfirmedTxApperances',
|
||||
'txApperances',
|
||||
'transactions'
|
||||
])
|
||||
assert.isArray(result.transactions)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#utxo', () => {
|
||||
it('should GET utxos for a single address', async () => {
|
||||
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 GET transactions for a single address', async () => {
|
||||
const addr =
|
||||
'2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7'
|
||||
|
||||
const result = await bchjs.OpenBazaar.tx(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.hasAllKeys(result, [
|
||||
'txid',
|
||||
'version',
|
||||
'vin',
|
||||
'vout',
|
||||
'blockhash',
|
||||
'blockheight',
|
||||
'confirmations',
|
||||
'blocktime',
|
||||
'valueOut',
|
||||
'valueIn',
|
||||
'fees',
|
||||
'hex',
|
||||
'time'
|
||||
])
|
||||
assert.isArray(result.vin)
|
||||
assert.isArray(result.vout)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function sleep (ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user