Compare commits

..
31 Commits
Author SHA1 Message Date
Chris Troutner 617bb16ddb Merge pull request #59 from Permissionless-Software-Foundation/ct-unstable
fix(price): Removing documentation for deprecated endpoint
2020-11-17 17:12:45 -08:00
Chris Troutner 83f14f5522 fix(price): Removing documentation for deprecated endpoint 2020-11-17 17:09:23 -08:00
Chris Troutner b8e22e1c99 Merge pull request #58 from Permissionless-Software-Foundation/ct-unstable
fix(price): Adding BCHA price
2020-11-17 14:47:47 -08:00
Chris Troutner 72d560e407 fix(price): Adding BCHA price 2020-11-17 14:41:04 -08:00
Chris Troutner 248b2fa2a6 Merge pull request #57 from Permissionless-Software-Foundation/ct-unstable
fix(basic auth): Fixing some bugs around basic auth
2020-11-12 09:52:29 -08:00
Chris Troutner 563cb297fe fix(basic auth): Fixing some bugs around basic auth 2020-11-12 09:48:54 -08:00
Chris Troutner 4c020240e1 fix(rate limits): Updated e2e tests for post-fork servers 2020-11-11 18:39:57 -08:00
Chris Troutner e070409a95 Merge pull request #56 from Permissionless-Software-Foundation/ct-unstable
Basic Authentication
2020-11-11 18:20:09 -08:00
Chris Troutner fbbd855145 feat(Basic Authentication): Adding authPass for auth token to all libraries 2020-11-11 17:47:46 -08:00
Chris Troutner 731987b35b fix(Basic Authentication): Adding back in 2020-11-11 14:56:53 -08:00
Chris Troutner 1e8e7b79f2 Updating comments in e2e rate limit tests 2020-11-11 14:11:13 -08:00
Chris Troutner 099eb25e88 Merge pull request #53 from Permissionless-Software-Foundation/ct-unstable
fix(blockbook): Removing documentation as a step towards deprecation
2020-11-10 08:44:32 -08:00
Chris Troutner 12a7c666c6 fix(blockbook): Removing documentation as a step towards deprecation 2020-11-10 08:39:26 -08:00
Chris Troutner e482e09e77 Merge pull request #52 from Permissionless-Software-Foundation/ninsight-tx-details
Add Ninsight TX Details
2020-11-10 08:27:12 -08:00
Chris Troutner 7ca6498ca0 feat(Ninsight): Adding TX Details endpoint 2020-11-10 08:24:19 -08:00
Chris Troutner f89b52ac86 Merge branch 'master' into ninsight-tx-details 2020-11-10 08:21:07 -08:00
Stoyan Zhekov 7990d0bffd Add Ninsight TX Details 2020-11-10 19:04:16 +09:00
Chris Troutner c0eaaf77c8 fix(integration tests): Updating scripts in package.json 2020-11-09 18:17:44 -08:00
Chris Troutner f424047a69 Merge pull request #51 from Permissionless-Software-Foundation/ninsight-tx-history
Add Ninsight TX History to bch-js
2020-11-09 16:14:39 -08:00
Chris Troutner fc0d8b7f8c fix(ninsight): Adding tx history endpoint 2020-11-09 16:12:10 -08:00
Chris Troutner 4551d1ca99 Merge pull request #50 from Permissionless-Software-Foundation/ninsight-unconfirmed-utxos
Add Ninsight Unconfirmed UTXOs
2020-11-09 15:47:11 -08:00
Chris Troutner b8083c6b88 fix(ninsight): Adding unconfirmed UTXOs endpoint 2020-11-09 15:45:11 -08:00
Stoyan Zhekov 0ef8555837 Add Ninsight TX History to bch-js 2020-11-09 19:49:41 +09:00
Stoyan Zhekov a7564ce611 Add Ninsight Unconfirmed UTXOs 2020-11-09 17:44:09 +09:00
Chris Troutner 601b87cb4a Updating README 2020-11-08 19:14:43 -08:00
Chris Troutner edfcc92b7b Merge pull request #48 from Permissionless-Software-Foundation/ct-unstable
Updating README
2020-11-08 19:04:29 -08:00
Chris Troutner a32e0da9be Updating README 2020-11-08 19:02:30 -08:00
Chris Troutner a1bf617d91 Updating README 2020-11-08 18:56:48 -08:00
Chris Troutner 33d2da503d Updating READMe 2020-11-08 18:49:45 -08:00
Chris Troutner c2ff1e2d68 Updating npm lib 2020-11-08 17:46:40 -08:00
Chris Troutner cc9e8c0319 Fixing links in README 2020-11-08 17:38:11 -08:00
35 changed files with 1192 additions and 441 deletions
+42 -52
View File
@@ -1,68 +1,71 @@
# bch-js
[![Build Status](https://travis-ci.org/christroutner/bch-js.svg?branch=master)](https://travis-ci.org/christroutner/bch-js)
[![Version](https://img.shields.io/npm/v/@chris.troutner/bch-js)](https://www.npmjs.com/package/@chris.troutner/bch-js)
[![Downloads/week](https://img.shields.io/npm/dw/@chris.troutner/bch-js)](https://npmjs.org/package/@chris.troutner/bch-js)
[![License](https://img.shields.io/npm/l/@chris.troutner/bch-js)](https://github.com/christroutner/bch-js/blob/master/LICENSE.md)
[![Build Status](https://travis-ci.org/Permissionless-Software-Foundation/bch-js.svg?branch=master)](https://travis-ci.org/Permissionless-Software-Foundation/bch-js)
[![Version](https://img.shields.io/npm/v/@psf/bch-js)](https://www.npmjs.com/package/@psf/bch-js)
[![Downloads/week](https://img.shields.io/npm/dw/@psf/bch-js)](https://npmjs.org/package/@psf/bch-js)
[![License](https://img.shields.io/npm/l/@psf/bch-js)](https://github.com/Permissionless-Software-Foundation/bch-js/blob/master/LICENSE.md)
[bch-js](https://www.npmjs.com/package/@chris.troutner/bch-js) is a JavaScript npm library for creating web and mobile apps for interacting with the Bitcoin Cash (BCH) blockchain. It can be used for free, but requires an account on [FullStack.cash](https://fullstack.cash) for increased rate limits. Find out more from [this article](https://troutsblog.com/research/bitcoin-cash/how-to-bch-full-stack-developer).
[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.
### Quick Start Videos:
Here are two YouTube walk-through videos to help you get started:
- [Introduction to bch-js and the bch-js-examples repository](https://youtu.be/GD2i1ZUiyrk)
- [Working with the FullStack.cash JWT token](https://youtu.be/GD2i1ZUiyrk)
### Quick Links
- [npm Library](https://www.npmjs.com/package/@chris.troutner/bch-js)
- [npm Library](https://www.npmjs.com/package/@psf/bch-js)
- [Documentation](https://bchjs.fullstack.cash/)
- [Examples](https://github.com/Permissionless-Software-Foundation/bch-js-examples)
- [api.fullstack.cash](https://api.fullstack.cash) - The REST API this library talks to by default.
- [bchn.fullstack.cash](https://bchn.fullstack.cash) - The REST API this library talks to by default.
- [FullStack.cash](https://fullstack.cash) - cloud-based infrastructure for application developers.
- [FullStack.cash Account](https://fullstack.cash/login) - Get your API key to unlock increased rate limits.
- [FullStack.cash](https://fullstack.cash) - cloud-based infrastructure for application
developers.
- [Permissionless Software Foundation](https://psfoundation.cash) - The organization that maintains this library.
### Quick Notes
- Install library: `npm install @chris.troutner/bch-js`
- Install library: `npm install @psf/bch-js`
- Instantiate the library in your code:
```
const BCHJS = require("@chris.troutner/bch-js")
let bchjs = new BCHJS()
const BCHJS = require("@psf/bch-js")
let bchjs = new BCHJS() // Defaults to BCHN network.
// testnet
bchjs = new BCHJS({ restURL: 'https://tapi.fullstack.cash/v3/' })
bchjs = new BCHJS({ restURL: 'https://testnet3.fullstack.cash/v3/' })
```
This is a fork of the [BITBOX SDK](https://github.com/Bitcoin-com/bitbox-sdk) (which is maintained by Bitcoin.com). This library is intended to be paired with
the [bch-api](https://github.com/christroutner/bch-api) REST API.
This library is intended to be paired with
the [bch-api](https://github.com/Permissionless-Software-Foundation/bch-api) REST API, and the infrastructure provided by [FullStack.cash](https://fullstack.cash). The `restURL` property can be changed to work with different Bitcoin Cash networks:
If you need a backward-compatible instance of this library, you can use a
'shim'. Do it like this:
```
const BCHJS = require("@chris.troutner/bch-js")
const bitbox = BCHJS.BitboxShim({ restURL: 'https://api.fullstack.cash/v3/' })
```
- BCHN Mainnet REST API server: https://bchn.fullstack.cash/v3/
- ABC Mainnet REST API server: https://abc.fullstack.cash/v3/
- Testnet3 REST API server: https://testnet3.fullstack.cash/v3/
- Check server status: https://metrics.fullstack.cash
### API Key
The [bch-api](https://github.com/christroutner/bch-api) REST API hosted by [FullStack.cash](https://fullstack.cash) uses JWT tokens to pay for increased
rate limits when interacting with the back end server. See [this article](https://troutsblog.com/research/bitcoin-cash/how-to-bch-full-stack-developer) if you want to understand the system-as-a-whole. The JWT token can be fed to bch-js *implicitly* or *explicitly*.
- Implicitly: bch-js will detect your JWT token by setting the `BCHJSTOKEN` environment variable.
The [bch-api](https://github.com/Permissionless-Software-Foundation/bch-api) REST API hosted by [FullStack.cash](https://fullstack.cash) uses JWT tokens to pay for increased
rate limits when interacting with the back end server. See [this article](https://troutsblog.com/research/bitcoin-cash/how-to-bch-full-stack-developer) if you want to understand the system-as-a-whole. The JWT token can be fed to bch-js _implicitly_ or _explicitly_.
- Implicitly: bch-js will detect your JWT token if you set the `BCHJSTOKEN` environment variable.
- Explicitly: You can directly feed in the JWT token with the `apiToken` property when instantiating the library. Here is an example:
```
const BCHJS = require("@chris.troutner/bch-js")
const BCHJS = require("@psf/bch-js")
let bchjs = new BCHJS({
restURL: 'https://api.fullstack.cash/v3/',
restURL: 'https://bchn.fullstack.cash/v3/',
apiToken: 'eyJhbGciO...' // Your JWT token here.
})
```
### Gatsby
bch-js is included in this [gatsby-ipfs-template](https://github.com/Permissionless-Software-Foundation/gatsby-ipfs-template) for building uncensorable web apps that can interact with the blockchain. When building a Gatsby (or other front-end app that uses Webpack), you'll need to add these lines to your `gatsby-node.js` file, as per [this issue](https://github.com/gatsbyjs/gatsby/issues/564):
```
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
@@ -75,60 +78,47 @@ exports.onCreateWebpackConfig = ({ actions }) => {
This is because the new IPFS class in bch-js uses the fs library for uploading files, which is not supported by Gatsby.
We also provide [minimal-slp-wallet-web](https://www.npmjs.com/package/minimal-slp-wallet-web) as a basic Bitcoin Cash wallet with SLP support, for front end projects. bch-js is encapsulated inside the instantiation of the library Class.
## Features
This library sets itself apart from BITBOX with the following features:
- [ECMAScript 2017 standard JavaScript](https://en.wikipedia.org/wiki/ECMAScript#8th_Edition_-_ECMAScript_2017) used instead of TypeScript. Works
natively with node.js v10 or higher.
natively with node.js v10 or higher.
- Full SLP tokens support: bch-js has full support for all SLP token functionality, including send, mint, and genesis transactions. It also fully support all aspects of [non-fugible tokans (NFTs)](https://www.youtube.com/watch?v=vvlpYUx6HRs).
- [Semantic Release](https://github.com/semantic-release/semantic-release) for
continuous delivery using semantic versioning.
continuous delivery using semantic versioning.
- [Greenkeeper](https://greenkeeper.io/) automatic dependency management for
automatically maintaining the latest, most secure dependencies.
automatically maintaining the latest, most secure dependencies.
- [IPFS uploads](https://ipfs.io) of all files and dependencies, to backup
dependencies in case they are ever inaccessible from GitHub or npm.
dependencies in case they are ever inaccessible from GitHub or npm.
## Documentation:
Full documentation for this library can be found here:
- [Documentation](https://bchjs.fullstack.cash/)
Original documentation on BITBOX is available at:
- [General docs](https://developer.bitcoin.com)
- [BITBOX Introduction](https://developer.bitcoin.com/bitbox)
- [BITBOX API Reference](https://developer.bitcoin.com/bitbox/docs/getting-started)
bch-js uses [APIDOC](http://apidocjs.com/) so that documentation and working code
live in the same repository. To generate the documentation:
- `npm run docs`
- Open the generated `docs/index.html` file in a web browser.
## Support
Have questions? Need help? Join our community support
[Telegram channel](https://t.me/bch_js_toolkit)
## IPFS Releases
I will periodically publish IPFS releases of this repository, including all
dependencies in the `node_modules` folder. This ensures working copies of this
repository can be retrieved in case there is any drift in dependency files, or
if dependencies are pulled from npm or GitHub.
Copies of this repository are also published on [IPFS](https://ipfs.io).
- Initial fork on 5/9/2019:
- without node_modules folder: QmQFHfbBQdEHfhtiRLbXtX1NcgnfL45hZb7TbQimTXAuzG (4 MB)
- with node_modules folder: QmXq9Ds6Qdkg9xbRhcF8pay9KabA6QN2y7bx3wvSqiXifk (107 MB)
- v1.0.0 - refactored to pure JavaScript:
- without node_modules folder: QmNjFsiTZRMAUa9rZpXqZqivv9JLaNicwLSPHjyLB7PVDk (1 MB)
- with node_modules folder: Qma9ScApwBtuL7dpdSk7jpBFTxbqRdiR921WjyP75SU7bT (100 MB)
- v3.8.10: QmauhggzKDo9A9je5y2K6WRAp32JmGRFCw2ZFTiSnW8yot
## License
[MIT](LICENSE.md)
+4 -6
View File
@@ -9,16 +9,14 @@
"main": "src/bch-js",
"scripts": {
"test": "nyc mocha --timeout 30000 test/unit/",
"test:integration": "bash test/integration/test-free-tier-bchn.sh",
"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/v3/ IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/",
"test:integration:testnet": "IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/testnet/",
"test:integration:local": "RESTURL=http://localhost:3000/v3/ mocha --timeout 30000 test/integration",
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v3/ bash test/integration/test-free-tier-bchn.sh",
"test:integration:testnet:local": "RESTURL=http://localhost:4000/v3/ mocha --timeout 30000 test/integration/testnet",
"test:integration:free": "bash test/integration/test-free-tier.sh",
"test:integration:free:bchn": "IS_USING_FREE_TIER=true bash test/integration/test-free-tier-bchn.sh",
"test:integration:free:testnet": "bash test/integration/testnet/test-free-tier.sh",
"test:temp": "mocha --timeout 30000 -g '#Encryption' test/integration/",
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v3/ mocha --timeout 30000 test/integration/testnet",
"test:temp": "RESTURL=http://localhost:3000/v3/ mocha --timeout 30000 -g '#price' test/integration/",
"test:integration:api": "RESTURL=https://api.fullstack.cash/v3/ mocha --timeout 30000 test/integration",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
+17
View File
@@ -11,6 +11,23 @@ class Address {
this.restURL = tmp.restURL
this.apiToken = tmp.apiToken
this.authToken = config.authToken
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
}
/**
+19 -1
View File
@@ -55,9 +55,27 @@ class BCHJS {
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
// Generate a Basic Authentication token from an auth password
this.authToken = ""
if (this.authPass) {
// console.log(`bch-js initialized with authPass: ${this.authPass}`)
// Generate the header for Basic Authentication.
const combined = `fullstackcash:${this.authPass}`
var base64Credential = Buffer.from(combined).toString("base64")
this.authToken = `Basic ${base64Credential}`
}
const libConfig = {
restURL: this.restURL,
apiToken: this.apiToken
apiToken: this.apiToken,
authToken: this.authToken
}
// console.log(`apiToken: ${this.apiToken}`)
+18 -243
View File
@@ -1,6 +1,10 @@
/*
This library interacts with the REST API endpoints in bch-api that communicate
with the Blockbook API.
CT 11/10/20
These endpoints will be soon be deprecated. Blockbook is being fazed out in
favor of Fulcrum.
*/
const axios = require("axios")
@@ -11,184 +15,28 @@ class Blockbook {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// console.log(`Blockbook apiToken: ${this.apiToken}`)
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
_this = this
}
/**
* @api Blockbook.balance() balance()
* @apiName Blockbook Balance
* @apiGroup Blockbook
* @apiDescription Return Balance about an address.
*
* @apiExample Example usage:
* (async () => {
* try {
* let balance = await bchjs.Blockbook.balance('bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c');
* console.log(balance)
* } catch(error) {
* console.error(error)
* }
* })()
*
* //{
* // "page": 1,
* // "totalPages": 1,
* // "itemsOnPage": 1000,
* // "address": "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c",
* // "balance": "6000000",
* // "totalReceived": "10185868",
* // "totalSent": "4185868",
* // "unconfirmedBalance": "0",
* // "unconfirmedTxs": 0,
* // "txs": 41,
* // "txids": [
* // "d31dc2cf66fe4d3d3ae18e1065def58a64920746b1702b52f060e5edeea9883b",
* // "41e9a118765ecf7a1ba4487c0863e23dba343cc5880381a72f0365ac2546c5fa",
* // "2f902dec880568511cefa87b9dd761563edeba9c8ba784dc9fca2f7c8c4e6f97",
* // "eea57285462dd70dadcd431fc814857b3f81fe4d0a059a8c02c12fd7d33c02d1",
* // "282b3b296b6aed7122586ed69f7a57d35584eaf94a4d1b1ad7d1b05d36cb79d1",
* // "ac444896b3e32d17824fa6573eed3b89768c5c9085b7a71f3ba88e9d5ba67355",
* // "a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1",
* // "5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e",
* // "54edaa42ff3d6559884a84ebb9bf5ef255635902f5f23b4854245d6b093d41d4",
* // "2b0825188e909410a20a6fbdc58ff5ccf368844273f93f551222c91e6d0fa888",
* // "7a12ea2c83d0c8a5d0f643974b0f04bc19be185c9011ed8fc33255a61d3198bb",
* // "bd6aeeb0748251bb5dba7252ac766fb208c9909d7663c099568225d3bc998a7f",
* // "7898bb1a8c5d933f9c2b24270522e8705b897c2f8d5b1c3477a6b952f2fe22ae",
* // "8d35668a6838de8faa8dff5d8dedeb114bd8ffe6ae73d926264bc8328b2c46b5",
* // "741b4692a14088438ab142cf0865fcbf3977aa7dbd2aafa9bf5f45e75e5e199a",
* // "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e",
* // "376de807f63253584c3edb80f92832ea90e8fdd7d8e68b2602e230d1b015e311",
* // "eb5d0902e4a303f38223ecebb06bbf14da8a07d1ebb2d77a89dfb9e00e286c10",
* // "11205c557af139f382c43f1f09f223cf28c64d939951fd569e5a30eee6178ccd",
* // "ae05a78086b8d64db26d3047de3d6959a68f2a1ed3017ddf927e2c3b20a80b31",
* // "7e0fc3cac7504d45b0f2ce68e807e592f0edf17914ab618a4cb4d93403d11c98",
* // "1cafaacdfb85b0c33f496bf2c03c4f2ede508479bbad56ae99164dfd823a823f",
* // "788add6a5cd961bdf7ca6145a3112462e0e51523d84a4a48047407a795433947",
* // "49f09b616824a05eb14ae50c9fbc5d6a0c414d66a7d0b217aa75340c00ed8b85",
* // "00f075805adf2a34563ecca33071d660a4c1e91d7d7045282c54554ee4844739",
* // "8d048fd00cf375ba9bbea43730da1ce86fc3cb4026e1dd0e751c07fa50a652c6",
* // "ac0e82ea84f93444602a99199dd80793f79a8ece5ac86156d2fff34f0bad44b2",
* // "342f6815845797e0748f4716c923a0dc9b87de649b69925b36422f6d2dc23b7f",
* // "0839a16b2411a1220c64c4d32a4c9b1e77ac5f47558921cf7c0a2adf25e0eb41",
* // "62f42995711cb0308dac4203c5deaa2985f120559131e66aebc5164426fb6cee",
* // "2ada093fe13c9c04da9582bb304923ce08312eaec92560b9128cdb9e93c5f52f",
* // "e0aadd861a06993e39af932bb0b9ad69e7b37ef5843a13c6724789e1c94f3513",
* // "925490ce60334aca204d82a61b634d89fe4cc9de429c7b6cb5ec420df3e3be5e",
* // "60cb69f29c150378abe21d157858713f82c4e2122867597a2573474763a9e94e",
* // "369a589173969c1c882cfb2d82b1e0ec90076ec827ff9d0f32ffc115690c93c3",
* // "43324ef3f5fdd55b645ba14de8c0667be9b223d60b3d1dcd76cf8fdeb0fd32e4",
* // "d2985c9b1c5c18fc2f6a963b7cb850606c4a18fcb85619057211ce3c8bcec696",
* // "dded59fe377517e52918deae8912a096658ebf5ae61992d39953c8bc3932a11b",
* // "2dc053f55a666a3d2a08b1c680b704d62a55506d14ad884add87edcc56b9277d",
* // "544c15ce35c0f2e808d28f29d6587f1ec9276233e29856b7f2938cf0daef0026",
* // "81039b1d7b855b133f359f9dc65f776bd105650153a941675fedc504228ddbd3"
* // ]
* //}
*
*(async () => {
* try {
* let balance = await bchjs.Blockbook.balance(['bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c','1BFHGm4HzqgXXyNX8n7DsQno5DAC4iLMRA']);
* console.log(balance)
* } catch(error) {
* console.error(error)
* }
* })()
*
* //[
* // {
* // "page": 1,
* // "totalPages": 1,
* // "itemsOnPage": 1000,
* // "address": "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c",
* // "balance": "6000000",
* // "totalReceived": "10185868",
* // "totalSent": "4185868",
* // "unconfirmedBalance": "0",
* // "unconfirmedTxs": 0,
* // "txs": 41,
* // "txids": [
* // "d31dc2cf66fe4d3d3ae18e1065def58a64920746b1702b52f060e5edeea9883b",
* // "41e9a118765ecf7a1ba4487c0863e23dba343cc5880381a72f0365ac2546c5fa",
* // "2f902dec880568511cefa87b9dd761563edeba9c8ba784dc9fca2f7c8c4e6f97",
* // "eea57285462dd70dadcd431fc814857b3f81fe4d0a059a8c02c12fd7d33c02d1",
* // "282b3b296b6aed7122586ed69f7a57d35584eaf94a4d1b1ad7d1b05d36cb79d1",
* // "ac444896b3e32d17824fa6573eed3b89768c5c9085b7a71f3ba88e9d5ba67355",
* // "a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1",
* // "5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e",
* // "54edaa42ff3d6559884a84ebb9bf5ef255635902f5f23b4854245d6b093d41d4",
* // "2b0825188e909410a20a6fbdc58ff5ccf368844273f93f551222c91e6d0fa888",
* // "7a12ea2c83d0c8a5d0f643974b0f04bc19be185c9011ed8fc33255a61d3198bb",
* // "bd6aeeb0748251bb5dba7252ac766fb208c9909d7663c099568225d3bc998a7f",
* // "7898bb1a8c5d933f9c2b24270522e8705b897c2f8d5b1c3477a6b952f2fe22ae",
* // "8d35668a6838de8faa8dff5d8dedeb114bd8ffe6ae73d926264bc8328b2c46b5",
* // "741b4692a14088438ab142cf0865fcbf3977aa7dbd2aafa9bf5f45e75e5e199a",
* // "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e",
* // "376de807f63253584c3edb80f92832ea90e8fdd7d8e68b2602e230d1b015e311",
* // "eb5d0902e4a303f38223ecebb06bbf14da8a07d1ebb2d77a89dfb9e00e286c10",
* // "11205c557af139f382c43f1f09f223cf28c64d939951fd569e5a30eee6178ccd",
* // "ae05a78086b8d64db26d3047de3d6959a68f2a1ed3017ddf927e2c3b20a80b31",
* // "7e0fc3cac7504d45b0f2ce68e807e592f0edf17914ab618a4cb4d93403d11c98",
* // "1cafaacdfb85b0c33f496bf2c03c4f2ede508479bbad56ae99164dfd823a823f",
* // "788add6a5cd961bdf7ca6145a3112462e0e51523d84a4a48047407a795433947",
* // "49f09b616824a05eb14ae50c9fbc5d6a0c414d66a7d0b217aa75340c00ed8b85",
* // "00f075805adf2a34563ecca33071d660a4c1e91d7d7045282c54554ee4844739",
* // "8d048fd00cf375ba9bbea43730da1ce86fc3cb4026e1dd0e751c07fa50a652c6",
* // "ac0e82ea84f93444602a99199dd80793f79a8ece5ac86156d2fff34f0bad44b2",
* // "342f6815845797e0748f4716c923a0dc9b87de649b69925b36422f6d2dc23b7f",
* // "0839a16b2411a1220c64c4d32a4c9b1e77ac5f47558921cf7c0a2adf25e0eb41",
* // "62f42995711cb0308dac4203c5deaa2985f120559131e66aebc5164426fb6cee",
* // "2ada093fe13c9c04da9582bb304923ce08312eaec92560b9128cdb9e93c5f52f",
* // "e0aadd861a06993e39af932bb0b9ad69e7b37ef5843a13c6724789e1c94f3513",
* // "925490ce60334aca204d82a61b634d89fe4cc9de429c7b6cb5ec420df3e3be5e",
* // "60cb69f29c150378abe21d157858713f82c4e2122867597a2573474763a9e94e",
* // "369a589173969c1c882cfb2d82b1e0ec90076ec827ff9d0f32ffc115690c93c3",
* // "43324ef3f5fdd55b645ba14de8c0667be9b223d60b3d1dcd76cf8fdeb0fd32e4",
* // "d2985c9b1c5c18fc2f6a963b7cb850606c4a18fcb85619057211ce3c8bcec696",
* // "dded59fe377517e52918deae8912a096658ebf5ae61992d39953c8bc3932a11b",
* // "2dc053f55a666a3d2a08b1c680b704d62a55506d14ad884add87edcc56b9277d",
* // "544c15ce35c0f2e808d28f29d6587f1ec9276233e29856b7f2938cf0daef0026",
* // "81039b1d7b855b133f359f9dc65f776bd105650153a941675fedc504228ddbd3"
* // ]
* // },
* // {
* // "page": 1,
* // "totalPages": 1,
* // "itemsOnPage": 1000,
* // "address": "bitcoincash:qpcxf2sv9hjw08nvpgffpamfus9nmksm3chv5zqtnz",
* // "balance": "0",
* // "totalReceived": "36781097",
* // "totalSent": "36781097",
* // "unconfirmedBalance": "0",
* // "unconfirmedTxs": 0,
* // "txs": 11,
* // "txids": [
* // "11205c557af139f382c43f1f09f223cf28c64d939951fd569e5a30eee6178ccd",
* // "ae05a78086b8d64db26d3047de3d6959a68f2a1ed3017ddf927e2c3b20a80b31",
* // "7e0fc3cac7504d45b0f2ce68e807e592f0edf17914ab618a4cb4d93403d11c98",
* // "60cb69f29c150378abe21d157858713f82c4e2122867597a2573474763a9e94e",
* // "f737485aaee3c10b13013fa109bb6294b099246134ca9885f4cc332dbc6c9bb4",
* // "decd5b9c0c959e4e543182093e8f7f8bc7a6ecd96a8a062daaeff3667f8feca7",
* // "94e69a627a34ae27fca81d15fff4323a7ce1f7c275c7485762ce018221017632",
* // "e67c70787af7f3506263c9eda007f3d2d24bd750ff95b5c50a120d9118dfd807",
* // "8e5e00704a147d54028f94d52df7730e821b9c6cd4bd29494e5636f49c199d6a",
* // "15102827c108566ea5daf725c09079c1a3f42ef99d1eb68ea8c584f7b16ab87a",
* // "cc27be8846276612dfce5924b7be96556212f0f0e62bd17641732175edb9911e"
* // ]
* // }
* //
*
*/
async balance(address) {
try {
// Handle single address.
@@ -220,62 +68,6 @@ class Blockbook {
}
}
/**
* @api Blockbook.utxo() utxo()
* @apiName Blockbook Utxo
* @apiGroup Blockbook
* @apiDescription Return list of uxto for address.
*
* @apiExample Example usage:
* (async () => {
* try {
* let utxo = await bchjs.Blockbook.utxo('bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf');
* console.log(utxo);
* } catch(error) {
* console.error(error)
* }
* })()
*
* [{
* "txid": "7774e449c5a3065144cefbc4c0c21e6b69c987f095856778ef9f45ddd8ae1a41",
* "vout": 0,
* "value": "1000",
* "height": 604392,
* "confirmations": 25530,
* "satoshis": 1000
* }]
*
*
* (async () => {
* try {
* let utxo = await bchjs.Blockbook.utxo([
* "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
* "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c"
* ]);
* console.log(utxo);
* } catch(error) {
* console.error(error)
* }
* })()
*
* [
* [{
* "txid": "7774e449c5a3065144cefbc4c0c21e6b69c987f095856778ef9f45ddd8ae1a41",
* "vout": 0,
* "value": "1000",
* "height": 604392,
* "confirmations": 25530,
* "satoshis": 1000
* }],
* [{
* "txid": "d5228d2cdc77fbe5a9aa79f19b0933b6802f9f0067f42847fc4fe343664723e5",
* "vout": 0,
* "value": "6000",
* "confirmations": 0,
* "satoshis": 6000
* }]
* ]
*/
async utxo(address) {
try {
// Handle single address.
@@ -306,23 +98,6 @@ class Blockbook {
}
}
/**
* @api Blockbook.tx() tx()
* @apiName Blockbook Tx
* @apiGroup Blockbook
* @apiDescription Get details on a transaction.
*
* @apiExample Example usage:
* (async () => {
* try {
* let txDetails = await bchjs.Blockbook.tx(`5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392`);
* console.log(txDetails);
* } catch(error) {
* console.error(error)
* }
* })()
*
*/
async tx(txid) {
try {
// Handle single txid.
+14 -4
View File
@@ -11,11 +11,21 @@ class Blockchain {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+14 -4
View File
@@ -10,11 +10,21 @@ class Control {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+14 -5
View File
@@ -11,12 +11,21 @@ class ElectrumX {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`,
timeout: 15000
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+14 -5
View File
@@ -11,12 +11,21 @@ class Encryption {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.axios = axios
// console.log(`Blockbook apiToken: ${this.apiToken}`)
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+14 -4
View File
@@ -6,11 +6,21 @@ class Generating {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+14 -4
View File
@@ -6,11 +6,21 @@ class Mining {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+220 -2
View File
@@ -50,14 +50,16 @@ class Ninsight {
* // {
* // "txid": "d31dc2cf66fe4d3d3ae18e1065def58a64920746b1702b52f060e5edeea9883b",
* // "vout": 1,
* // "value": "1000000",
* // "amount": 0.03608203,
* // "satoshis": 3608203,
* // "height": 585570,
* // "confirmations": 10392
* // },
* // {
* // "txid": "41e9a118765ecf7a1ba4487c0863e23dba343cc5880381a72f0365ac2546c5fa",
* // "vout": 0,
* // "value": "1000000",
* // "amount": 0.03608203,
* // "satoshis": 3608203,
* // "height": 577125,
* // "confirmations": 18837
* // }
@@ -96,6 +98,222 @@ class Ninsight {
else throw error
}
}
/**
* @api Ninsight.unconfirmed() unconfirmed()
* @apiName Ninsight Unconfirmed Utxo
* @apiGroup Ninsight
* @apiDescription Returns a list of unconfirmed UTXOs for an address.
*
* @apiExample Example usage:
* (async () => {
* try {
* let utxo = await bchjs.Ninsight.unconfirmed('bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c');
* console.log(utxo);
* } catch(error) {
* console.error(error)
* }
* })()
*
* // [
* // {
* // "txid": "d31dc2cf66fe4d3d3ae18e1065def58a64920746b1702b52f060e5edeea9883b",
* // "vout": 1,
* // "amount": 0.03608203,
* // "satoshis": 3608203,
* // "confirmations": 0
* // "ts": 1559670801
* // },
* // {
* // "txid": "41e9a118765ecf7a1ba4487c0863e23dba343cc5880381a72f0365ac2546c5fa",
* // "vout": 0,
* // "amount": 0.03608203,
* // "satoshis": 3608203,
* // "confirmations": 0
* // "ts": 1559670902
* // }
* // ]
*
*/
async unconfirmed(address) {
try {
if (typeof address === "string") {
const response = await axios.post(
`${this.ninsightURL}/address/unconfirmed`,
{
addresses: [address]
},
_this.axiosOptions
)
return response.data
} else if (Array.isArray(address)) {
const response = await axios.post(
`${this.ninsightURL}/address/unconfirmed`,
{
addresses: address
},
_this.axiosOptions
)
return response.data
}
throw new Error(`Input address must be a string or array of strings.`)
} catch (error) {
if (error.response && error.response.data) throw error.response.data
else throw error
}
}
/**
* @api Ninsight.transactions() transactions()
* @apiName Ninsight TX History
* @apiGroup Ninsight
* @apiDescription Return transactions history for address.
*
* @apiExample Example usage:
* (async () => {
* try {
* let txs = await bchjs.Ninsight.transactions('bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c');
* console.log(txs);
* } catch(error) {
* console.error(error)
* }
* })()
*
* // [
* // {
* // "pagesTotal": 1,
* // "txs": [
* // {
* // "txid": "ec7bc8349386e3e1939bbdc4f8092fdbdd6a380734e68486b558cd594c451d5b",
* // "version": 2,
* // "locktime": 0,
* // "vin": [
* // {
* // "txid": "4f1fc57c33659628938db740449bf92fb75799e1d5750a4aeef80eb52d6df1e0",
* // "vout": 0,
* // "sequence": 4294967295,
* // "n": 0,
* // ...
* // }
* // ...
* // ]
* // ...
* // }
* // ],
* // "legacyAddress": "1LpbYkEM5cryfhs58tH8c93p4SGzit7UrP",
* // "cashAddress": "bitcoincash:qrvk436u4r0ew2wj0rd9pnxhx4w90p2yfc29ta0d2n",
* // "currentPage": 0
* // }
* // ]
* //
*
*/
async transactions(address) {
try {
if (typeof address === "string") {
const response = await axios.post(
`${this.ninsightURL}/address/transactions`,
{
addresses: [address]
},
_this.axiosOptions
)
return response.data
} else if (Array.isArray(address)) {
const response = await axios.post(
`${this.ninsightURL}/address/transactions`,
{
addresses: address
},
_this.axiosOptions
)
return response.data
}
throw new Error(`Input address must be a string or array of strings.`)
} catch (error) {
if (error.response && error.response.data) throw error.response.data
else throw error
}
}
/**
* @api Ninsight.txDetails() txDetails()
* @apiName Ninsight TX Details
* @apiGroup Ninsight
* @apiDescription Return transactions details for address(es).
*
* @apiExample Example usage:
* (async () => {
* try {
* let result = await bchjs.Ninsight.txDetails('fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33');
* console.log(result);
* } catch(error) {
* console.error(error)
* }
* })()
*
* // [
* // {
* // "txid": "fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
* // "version": 1,
* // "locktime": 0,
* // "vin": [
* // {
* // "sequence": 4294967295,
* // "n": 0
* // }
* // ],
* // "vout": [
* // ...
* // ],
* // "blockhash": "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09",
* // "blockheight": 1000,
* // "confirmations": 659909,
* // "time": 1232346882,
* // "blocktime": 1232346882,
* // "firstSeenTime": null,
* // "valueOut": 50,
* // "size": 135
* // }
* // ]
*
*/
async txDetails(txid) {
try {
if (typeof txid === "string") {
const response = await axios.post(
`${this.ninsightURL}/transaction/details`,
{
txids: [txid]
},
_this.axiosOptions
)
return response.data
} else if (Array.isArray(txid)) {
const response = await axios.post(
`${this.ninsightURL}/transaction/details`,
{
txids: txid
},
_this.axiosOptions
)
return response.data
}
throw new Error(`Transaction ID must be a string or array of strings.`)
} catch (error) {
if (error.response && error.response.data) throw error.response.data
else throw error
}
}
}
module.exports = Ninsight
+52 -28
View File
@@ -6,41 +6,30 @@ class Price {
constructor(config) {
_this = this
if (config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
}
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
this.axios = axios
}
/**
* @api price.current() current()
* @apiName Price.
* @apiGroup Price
* @apiDescription Return current price of BCH in multiple currencies.
* This endpoint will be deprecated in favor of getUSD. It uses the Bitcoin.com
* price feed.
*
* @apiExample Example usage:
*(async () => {
* try {
* let current = await bchjs.Price.current('usd');
* console.log(current);
* } catch(err) {
* console.err(err)
* }
*})()
*
* // 26681
*/
// This endpoint is deprecated. Documentation removed.
async current(currency = "usd") {
try {
const response = await this.axios.get(
@@ -132,6 +121,41 @@ class Price {
else throw err
}
}
/**
* @api price.getBchaUsd() getBchaUsd()
* @apiName Price getBchaUsd()
* @apiGroup Price
* @apiDescription Return current price of BCHA in USD.
* This endpoint gets the USD price of BCHA from the Coinex API. The price
* comes from bch-api, so it has a better chance of working in Tor.
*
* @apiExample Example usage:
*(async () => {
* try {
* let current = await bchjs.Price.getBchaUsd();
* console.log(current);
* } catch(err) {
* console.err(err)
* }
*})()
*
* // 18.81
*/
async getBchaUsd() {
try {
const response = await this.axios.get(
`${this.restURL}price/bchausd`,
_this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
return response.data.usd
} catch (err) {
if (err.response && err.response.data) throw err.response.data
else throw err
}
}
}
module.exports = Price
+16 -10
View File
@@ -6,11 +6,21 @@ class RawTransactions {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
@@ -262,9 +272,7 @@ class RawTransactions {
txids: txid,
verbose: verbose
},
headers: {
authorization: `Token ${this.apiToken}`
}
headers: _this.axiosOptions.headers
}
const response = await axios(options)
@@ -337,9 +345,7 @@ class RawTransactions {
data: {
hexes: hex
},
headers: {
authorization: `Token ${this.apiToken}`
}
headers: _this.axiosOptions.headers
}
const response = await axios(options)
+14 -4
View File
@@ -4,11 +4,21 @@ class Schnorr {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
}
+20 -11
View File
@@ -18,22 +18,31 @@ const Utils = require("./utils")
// SLP is a superset of BITBOX
class SLP {
constructor(config) {
const tmp = {}
if (!config || !config.restURL) {
tmp.restURL = `https://api.fullstack.cash/v3/`
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
tmp.restURL = config.restURL
tmp.apiToken = config.apiToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
this.restURL = tmp.restURL
this.apiToken = tmp.apiToken
this.Address = new Address(tmp)
this.Address = new Address(config)
this.ECPair = ECPair
this.TokenType1 = new TokenType1(tmp)
this.TokenType1 = new TokenType1(config)
this.NFT1 = new NFT1(this.restURL)
this.Utils = new Utils(tmp)
this.Utils = new Utils(config)
}
}
+17 -6
View File
@@ -18,17 +18,28 @@ class TokenType1 {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
addy = new Address(config)
this.Script = new Script()
this.axios = axios
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
// Instantiate the transaction builder.
TransactionBuilder.setAddress(addy)
+14 -4
View File
@@ -13,11 +13,21 @@ class Utils {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.slpParser = slpParser
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
+14 -4
View File
@@ -6,11 +6,21 @@ class Util {
constructor(config) {
this.restURL = config.restURL
this.apiToken = config.apiToken
this.authToken = config.authToken
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
if (this.authToken) {
// Add Basic Authentication token to the authorization header.
this.axiosOptions = {
headers: {
authorization: this.authToken
}
}
} else {
// Add JWT token to the authorization header.
this.axiosOptions = {
headers: {
authorization: `Token ${this.apiToken}`
}
}
}
@@ -5,11 +5,17 @@
To Run Test:
- Update the RESTURL for bch-api you want to test against.
- Ensure the BCHJSTOKEN environment variable is set to an empty string.
- If working with bch-api locally, eliminate the local IP address from the
whitelist in bch-api/src/middleware/route-ratelimit.js
Run this test with this command:
mocha --timeout=30000 anonymous-rate-limits.js
*/
const assert = require("chai").assert
const RESTURL = `https://api.fullstack.cash/v3/`
// const RESTURL = `https://abc.fullstack.cash/v3/`
const RESTURL = `https://bchn.fullstack.cash/v3/`
// const RESTURL = `http://localhost:3000/v3/`
const BCHJS = require("../../../src/bch-js")
@@ -24,7 +30,7 @@ describe("#anonymous rate limits", () => {
it("should allow an anonymous call to an indexer", async () => {
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
const result = await bchjs.Blockbook.balance(addr)
const result = await bchjs.Electrumx.balance(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "balance")
@@ -32,7 +38,7 @@ describe("#anonymous rate limits", () => {
it("should throw error when rate limit exceeded", async () => {
try {
for (let i = 0; i < 22; i++) await bchjs.Control.getNetworkInfo()
for (let i = 0; i < 35; i++) await bchjs.Control.getNetworkInfo()
assert.fail("Unexpected result")
} catch (err) {
@@ -0,0 +1,56 @@
/*
Mocha test that verifies that the bch-api server is enforcing its
access rules for Basic Authentication.
To Run Test:
- Update the restURL for bch-api you want to test against.
- Update the PRO_PASS value with a current PRO_PASSES string used by bch-api.
*/
const assert = require("chai").assert
const PRO_PASS = "testpassword"
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS({
// restURL: `https://bchn.fullstack.cash/v3/`,
restURL: `https://abc.fullstack.cash/v3/`,
// restURL: `http://localhost:3000/v3/`,
authPass: PRO_PASS
})
describe("#Basic Authentication rate limits", () => {
it("should allow more than 20 RPM to full node", async () => {
for (let i = 0; i < 22; i++) {
const result = await bchjs.Control.getNetworkInfo()
if (i === 5) {
// console.log(`validating 5th call: ${i}`)
assert.property(result, "version", "more than 3 calls allowed")
}
if (i === 15) {
// console.log(`validating 5th call: ${i}`)
assert.property(result, "version", "more than 10 calls allowed")
}
}
}).timeout(45000)
it("should allow more than 20 RPM to an indexer", async () => {
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
for (let i = 0; i < 22; i++) {
const result = await bchjs.Blockbook.balance(addr)
if (i === 5) {
// console.log(`validating 5th call: ${i}`)
assert.property(result, "balance", "more than 3 calls allowed")
}
if (i === 15) {
// console.log(`validating 5th call: ${i}`)
assert.property(result, "balance", "more than 10 calls allowed")
}
}
}).timeout(45000)
})
+4
View File
@@ -1,4 +1,8 @@
/*
CT 11/11/2020:
There is no longer a free tier. These tests have been deprecated.
--------
Mocha test that verifies that the bch-api server is enforcing its
FREE access rules
@@ -1,4 +1,8 @@
/*
CT 11/11/2020:
There is no longer a free tier. These tests have been deprecated.
----
Mocha test that verifies that the bch-api server is enforcing its
full-node access rules
@@ -14,7 +18,8 @@ const JWT_TOKEN =
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS({
restURL: `https://api.fullstack.cash/v3/`,
// restURL: `https://bchn.fullstack.cash/v3/`,
restURL: `https:/abc.fullstack.cash/v3/`,
// restURL: `http://localhost:3000/v3/`,
apiToken: JWT_TOKEN
})
@@ -22,7 +27,7 @@ const bchjs = new BCHJS({
describe("#full node rate limits", () => {
it("should allow an free call to an indexer", async () => {
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
const result = await bchjs.Blockbook.balance(addr)
const result = await bchjs.Electrumx.balance(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "balance")
+4 -3
View File
@@ -14,12 +14,13 @@ const JWT_TOKEN =
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS({
restURL: `https://api.fullstack.cash/v3/`,
// restURL: `https://bchn.fullstack.cash/v3/`,
restURL: `https://abc.fullstack.cash/v3/`,
// restURL: `http://localhost:3000/v3/`,
apiToken: JWT_TOKEN
})
describe("#full node rate limits", () => {
describe("#Indexer rate limits", () => {
it("should allow more than 20 RPM to full node", async () => {
for (let i = 0; i < 22; i++) {
const result = await bchjs.Control.getNetworkInfo()
@@ -40,7 +41,7 @@ describe("#full node rate limits", () => {
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
for (let i = 0; i < 22; i++) {
const result = await bchjs.Blockbook.balance(addr)
const result = await bchjs.Electrumx.balance(addr)
if (i === 5) {
// console.log(`validating 5th call: ${i}`)
+72
View File
@@ -54,4 +54,76 @@ describe(`#Ninsight`, () => {
assert.property(result[0], "asm")
})
})
describe(`#transactions`, () => {
it(`should POST transactions history for a single address`, async () => {
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 transactions history for an array of addresses`, async () => {
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")
assert.property(result[0].txs[0], "vin")
assert.property(result[0].txs[0], "vout")
})
})
describe(`#txDetails`, () => {
it(`should POST transactions details for a single address`, async () => {
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 transactions details for an array of addresses`, async () => {
const txid = [
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
]
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")
})
})
})
+9
View File
@@ -21,6 +21,15 @@ describe("#price", () => {
})
})
describe("#getBchaUsd", () => {
it("should get the USD price of BCHA", async () => {
const result = await bchjs.Price.getBchaUsd()
console.log(result)
assert.isNumber(result)
})
})
describe("#rates", () => {
it("should get the price of BCH in several currencies", async () => {
const result = await bchjs.Price.rates()
+71
View File
@@ -60,6 +60,77 @@ describe(`#Ninsight`, () => {
assert.property(result[0], "asm")
})
})
describe(`#transactions`, () => {
it(`should POST transactions history for a single address`, async () => {
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 transactions history for an array of addresses`, async () => {
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")
assert.property(result[0].txs[0], "vin")
assert.property(result[0].txs[0], "vout")
})
})
describe(`#txDetails`, () => {
it(`should POST transactions details for a single address`, async () => {
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], "valueOut")
assert.property(result[0], "size")
})
it(`should POST transactions details for an array of addresses`, async () => {
const txid = [
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
]
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")
})
})
})
function sleep(ms) {
+9
View File
@@ -25,6 +25,15 @@ describe("#price", () => {
})
})
describe("#getBchaUsd", () => {
it("should get the USD price of BCHA", async () => {
const result = await bchjs.Price.getBchaUsd()
console.log(result)
assert.isNumber(result)
})
})
describe("#rates", () => {
it("should get the price of BCH in several currencies", async () => {
const result = await bchjs.Price.rates()
@@ -1,6 +1,6 @@
#!/bin/bash
#export RESTURL=https://bchn.fullstack.cash/v3/
export RESTURL=https://bchn.fullstack.cash/v3/
#export RESTURL=http://localhost:3000/v3/
#export IS_USING_FREE_TIER=true
-8
View File
@@ -1,8 +0,0 @@
#!/bin/bash
export RESTURL=https://free-main.fullstack.cash/v3/
#export RESTURL=http://localhost:3000/v3/
export IS_USING_FREE_TIER=true
cd test/integration/
mocha --timeout 30000 blockchain.js control.js electrumx.js ninsight.js openbazaar.js price.js rawtransaction.js slp.js util.js
+71
View File
@@ -68,6 +68,77 @@ describe(`#Ninsight`, () => {
// ])
})
})
describe(`#transactions`, () => {
it(`should POST transactions history for a single address`, async () => {
const addr = "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr"
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 transactions history for an array of addresses`, async () => {
const addr = [
"bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr",
"bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul"
]
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")
})
})
describe(`#txDetails`, () => {
it(`should POST transactions details for a single address`, async () => {
const txid = "76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea"
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], "valueOut")
assert.property(result[0], "size")
})
it(`should POST transactions details for an array of addresses`, async () => {
const txid = [
"f191d1062789d7071da6f2168ba306869a829294f6b1c09d03492db4ca3a8e77",
"76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea"
]
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")
})
})
})
function sleep(ms) {
-25
View File
@@ -1,25 +0,0 @@
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../src/bch-js")
// Used for debugging and iterrogating JS objects.
const util = require("util")
util.inspect.defaultOptions = { depth: 1 }
describe(`#BitboxShim`, () => {
it("should create the shim library", () => {
const BitboxShim = BCHJS.BitboxShim()
const bitbox = new BitboxShim()
//console.log(`bitbox.Address: ${util.inspect(bitbox.Address)}`)
assert.hasAnyKeys(bitbox.Address, [
// "details",
// "utxo",
// "unconfirmed",
// "transactions",
// "toLegacyAddress"
"restURL"
])
})
})
+142 -1
View File
@@ -21,9 +21,150 @@ const utxo = {
"OP_DUP OP_HASH160 2fe2c4c5ef359bb2fe1a849f891cecffbcfb4f77 OP_EQUALVERIFY OP_CHECKSIG"
}
const unconfirmed = {
utxos: [
{
txid: "3904ffe6f8fba4ceda5e887130f60fcb18bdc7dcee10392a57f89475c5c108f1",
vout: 0,
amount: 0.03608203,
satoshis: 3608203,
confirmations: 0,
ts: 1559670801
}
],
legacyAddress: "1AyWs8U4HUnTLmxxFiGoJbsXauRsvBrcKW",
cashAddress: "bitcoincash:qpkkjkhe29mqhqmu3evtq3dsnruuzl3rku6usknlh5",
slpAddress: "simpleledger:qpkkjkhe29mqhqmu3evtq3dsnruuzl3rkuk8mdxlf2",
scriptPubKey: "76a9146d695af951760b837c8e58b045b098f9c17e23b788ac"
}
const utxoPost = [utxo, utxo]
const unconfirmedPost = [unconfirmed, unconfirmed]
const transactions = {
pagesTotal: 1,
txs: [
{
txid: "ec7bc8349386e3e1939bbdc4f8092fdbdd6a380734e68486b558cd594c451d5b",
version: 2,
locktime: 0,
vin: [
{
txid:
"4f1fc57c33659628938db740449bf92fb75799e1d5750a4aeef80eb52d6df1e0",
vout: 0,
sequence: 4294967295,
n: 0,
scriptSig: {
hex:
"483045022100a3662a19ae384a1ceddea57765e425e61b04823e976d574da3911ac6b55d7f9b02200e571d985bce987675a2d58587a346fa40c39f4df13dc88548a92c52d5b24422412103f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f",
asm:
"3045022100a3662a19ae384a1ceddea57765e425e61b04823e976d574da3911ac6b55d7f9b02200e571d985bce987675a2d58587a346fa40c39f4df13dc88548a92c52d5b24422[ALL|FORKID] 03f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f"
},
addr: "17HPz8RQ4XM6mjre6aspvqyj1j648CZidM",
valueSat: 1111,
value: 0.00001111,
doubleSpentTxID: null
},
{
txid:
"126d62c299e7e14c66fe0b485d13082c23641f003690462046bc24ad2d1180c1",
vout: 0,
sequence: 4294967295,
n: 1,
scriptSig: {
hex:
"47304402203e3f923207111ff9bbd2fb5ab1a49a9145ad809ee0cad0e0ddaed64bfe38dc16022012ee288fb413bd500c63f8bb95e46b6b57d34762decd46b7188478a1c398eeda412103f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f",
asm:
"304402203e3f923207111ff9bbd2fb5ab1a49a9145ad809ee0cad0e0ddaed64bfe38dc16022012ee288fb413bd500c63f8bb95e46b6b57d34762decd46b7188478a1c398eeda[ALL|FORKID] 03f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f"
},
addr: "17HPz8RQ4XM6mjre6aspvqyj1j648CZidM",
valueSat: 1000,
value: 0.00001,
doubleSpentTxID: null
}
],
vout: [
{
value: "0.00001736",
n: 0,
scriptPubKey: {
hex: "76a914d96ac75ca8df9729d278da50ccd7355c5785444e88ac",
asm:
"OP_DUP OP_HASH160 d96ac75ca8df9729d278da50ccd7355c5785444e OP_EQUALVERIFY OP_CHECKSIG",
addresses: ["1LpbYkEM5cryfhs58tH8c93p4SGzit7UrP"],
type: "pubkeyhash"
},
spentTxId: null,
spentIndex: null,
spentHeight: null
}
],
blockheight: -1,
confirmations: 0,
time: 1559673337,
valueOut: 0.00001736,
size: 339,
valueIn: 0.00002111,
fees: 0.00000375
}
],
legacyAddress: "1LpbYkEM5cryfhs58tH8c93p4SGzit7UrP",
cashAddress: "bitcoincash:qrvk436u4r0ew2wj0rd9pnxhx4w90p2yfc29ta0d2n",
currentPage: 0
}
const transactionsPost = [transactions, transactions]
const details = {
txid: "fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
version: 1,
locktime: 0,
vin: [
{
coinbase: "04ffff001d02fd04",
sequence: 4294967295,
n: 0
}
],
vout: [
{
value: "50.00000000",
n: 0,
scriptPubKey: {
hex:
"4104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac",
asm:
"04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a OP_CHECKSIG",
addresses: ["1BW18n7MfpU35q4MTBSk8pse3XzQF8XvzT"],
type: "pubkeyhash",
cashAddrs: ["bitcoincash:qpej6mkrwca4tvy2snq4crhrf88v4ljspysx0ueetk"]
},
spentTxId: null,
spentIndex: null,
spentHeight: null
}
],
blockhash:
"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09",
blockheight: 1000,
confirmations: 585610,
time: 1232346882,
blocktime: 1232346882,
isCoinBase: true,
valueOut: 50,
size: 135
}
const detailsPost = [details, details]
module.exports = {
utxo,
utxoPost
utxoPost,
unconfirmed,
unconfirmedPost,
transactions,
transactionsPost,
details,
detailsPost
}
+174
View File
@@ -78,4 +78,178 @@ describe(`#Ninsight`, () => {
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")
})
})
})
+12 -1
View File
@@ -5,7 +5,7 @@ const sinon = require("sinon")
const mockDataLib = require("./fixtures/price-mocks")
let mockData
describe("#Price", () => {
describe("#price", () => {
let sandbox
let bchjs
@@ -56,4 +56,15 @@ describe("#Price", () => {
assert.property(result, "CAD")
})
})
describe("#getBchaUsd", () => {
it("should get the USD price of BCHA", async () => {
sandbox.stub(bchjs.Price.axios, "get").resolves({ data: { usd: 18.87 } })
const result = await bchjs.Price.getBchaUsd()
// console.log(result)
assert.isNumber(result)
})
})
})