mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-22 00:52:01 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
611c7977ef | ||
|
|
39ac634675 | ||
|
|
278a54bd9b | ||
|
|
30b1f71d81 | ||
|
|
e7d7fc1019 | ||
|
|
524da532e2 | ||
|
|
aef56c5c14 | ||
|
|
e2ba265878 | ||
|
|
2472dc3606 | ||
|
|
2df36124b4 | ||
|
|
c422d8db34 | ||
|
|
ec2d8ea80a | ||
|
|
fc527834ea | ||
|
|
3ceebc1f12 | ||
|
|
2ff46c1f76 | ||
|
|
6926bbe113 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright 2020 Chris Troutner
|
||||
Copyright 2021 Chris Troutner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -35,15 +35,15 @@ const BCHJS = require("@psf/bch-js")
|
||||
let bchjs = new BCHJS() // Defaults to BCHN network.
|
||||
|
||||
// testnet
|
||||
bchjs = new BCHJS({ restURL: 'https://testnet3.fullstack.cash/v3/' })
|
||||
bchjs = new BCHJS({ restURL: 'https://testnet3.fullstack.cash/v4/' })
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
- 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/
|
||||
- BCHN Mainnet REST API server: https://bchn.fullstack.cash/v4/
|
||||
- ABC Mainnet REST API server: https://abc.fullstack.cash/v4/
|
||||
- Testnet3 REST API server: https://testnet3.fullstack.cash/v4/
|
||||
- Check server status: https://metrics.fullstack.cash
|
||||
|
||||
### API Key
|
||||
@@ -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
|
||||
|
||||
|
||||
Generated
+772
-243
File diff suppressed because it is too large
Load Diff
+5
-6
@@ -14,10 +14,10 @@
|
||||
"test:integration:bchn": "export RESTURL=https://bchn.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
|
||||
"test:integration:testnet": "IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/chains/testnet/",
|
||||
"test:integration:local": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration",
|
||||
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v4/ bash test/integration/test-bchn-integration.sh",
|
||||
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
|
||||
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v4/ mocha --timeout 30000 test/integration/testnet",
|
||||
"test:temp": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#getStatus' test/integration/",
|
||||
"test:temp2": "mocha --timeout 30000 -g '#getStatus' test/unit/",
|
||||
"test:temp": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#tokenUtxoDetails' test/integration/",
|
||||
"test:temp2": "mocha --timeout 30000 -g '#generateSendOpReturn' test/unit/",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
|
||||
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
|
||||
@@ -32,9 +32,9 @@
|
||||
"dependencies": {
|
||||
"@uppy/core": "^1.10.4",
|
||||
"@uppy/tus": "^1.5.12",
|
||||
"apidoc": "^0.17.7",
|
||||
"apidoc": "^0.25.0",
|
||||
"assert": "^2.0.0",
|
||||
"axios": "^0.19.0",
|
||||
"axios": "^0.21.1",
|
||||
"bc-bip68": "^1.0.5",
|
||||
"bchaddrjs-slp": "^0.2.5",
|
||||
"bigi": "^1.4.2",
|
||||
@@ -87,7 +87,6 @@
|
||||
"husky": "^4.3.6",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"mocha": "^6.1.4",
|
||||
"nock": "^10.0.6",
|
||||
"node-mocks-http": "^1.7.0",
|
||||
"nyc": "^14.1.0",
|
||||
"prettier": "^1.18.2",
|
||||
|
||||
+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
|
||||
@@ -118,11 +118,11 @@ class TokenType1 {
|
||||
|
||||
// Convert the send quantity to the format expected by slp-mdm.
|
||||
const baseQty = sendQtyBig.toString()
|
||||
// console.log(`baseQty: `, baseQty)
|
||||
console.log('baseQty: ', baseQty)
|
||||
|
||||
// Convert the change quantity to the format expected by slp-mdm.
|
||||
const baseChange = change.toString()
|
||||
// console.log(`baseChange: `, baseChange)
|
||||
console.log('baseChange: ', baseChange)
|
||||
|
||||
// Check for potential burns
|
||||
const outputQty = new BigNumber(baseChange).plus(
|
||||
@@ -220,7 +220,12 @@ class TokenType1 {
|
||||
// Calculate the total amount of tokens owned by the wallet.
|
||||
let totalTokens = 0
|
||||
for (let i = 0; i < tokenUtxos.length; i++) {
|
||||
totalTokens += tokenUtxos[i].tokenQty
|
||||
totalTokens += parseFloat(tokenUtxos[i].tokenQty)
|
||||
}
|
||||
|
||||
// Make sure burn quantity isn't bigger than the total amount in tokens
|
||||
if (burnQty > totalTokens) {
|
||||
burnQty = totalTokens
|
||||
}
|
||||
|
||||
const remainder = totalTokens - burnQty
|
||||
|
||||
+15
-14
@@ -1073,17 +1073,18 @@ class Utils {
|
||||
for (let i = 0; i < utxos.length; i++) {
|
||||
const utxo = utxos[i]
|
||||
|
||||
if (!utxo.satoshis) {
|
||||
// If Electrumx, convert the value to satoshis.
|
||||
if (utxo.value) {
|
||||
utxo.satoshis = utxo.value
|
||||
} else {
|
||||
// If there is neither a satoshis or value property, throw an error.
|
||||
throw new Error(
|
||||
`utxo ${i} does not have a satoshis or value property.`
|
||||
)
|
||||
}
|
||||
}
|
||||
// CT 1/9/21: This code can be removed after 2/1/21
|
||||
// if (!utxo.satoshis) {
|
||||
// // If Electrumx, convert the value to satoshis.
|
||||
// if (utxo.value) {
|
||||
// utxo.satoshis = utxo.value
|
||||
// } else {
|
||||
// // If there is neither a satoshis or value property, throw an error.
|
||||
// throw new Error(
|
||||
// `utxo ${i} does not have a satoshis or value property.`
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!utxo.txid) {
|
||||
// If Electrumx, convert the tx_hash property to txid.
|
||||
@@ -1136,7 +1137,7 @@ class Utils {
|
||||
err.message.indexOf('trailing data') === -1)
|
||||
) {
|
||||
// console.log(
|
||||
// `unknown error from decodeOpReturn(). Marking as 'null'`,
|
||||
// 'unknown error from decodeOpReturn(). Marking as \'null\'',
|
||||
// err
|
||||
// )
|
||||
|
||||
@@ -1147,7 +1148,7 @@ class Utils {
|
||||
// an SLP UTXO.
|
||||
// Mark as false and continue the loop.
|
||||
} else {
|
||||
// console.log("marking as invalid")
|
||||
// console.log('marking as invalid')
|
||||
utxo.isValid = false
|
||||
outAry.push(utxo)
|
||||
}
|
||||
@@ -1254,7 +1255,7 @@ class Utils {
|
||||
|
||||
// Figure out what token quantity is represented by this utxo.
|
||||
const tokenQty = slpData.amounts[utxo.vout - 1]
|
||||
// console.log(`tokenQty: `, tokenQty)
|
||||
// console.log('tokenQty: ', tokenQty)
|
||||
|
||||
if (!tokenQty) {
|
||||
// outAry[i] = false
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -743,8 +743,8 @@ describe('#SLP', () => {
|
||||
const tokenUtxos = [
|
||||
{
|
||||
tokenId:
|
||||
'0a321bff9761f28e06a268b14711274bb77617410a16807bd0437ef234a072b1',
|
||||
decimals: 0,
|
||||
'38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
|
||||
decimals: 8,
|
||||
tokenQty: 2
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
const assert = require('chai').assert
|
||||
const nock = require('nock') // http call mocking
|
||||
const sinon = require('sinon')
|
||||
// const axios = require("axios")
|
||||
|
||||
@@ -24,17 +23,10 @@ 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()
|
||||
})
|
||||
|
||||
|
||||
+21
-10
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
const assert = require('chai').assert
|
||||
const nock = require('nock') // http call mocking
|
||||
const sinon = require('sinon')
|
||||
// const axios = require("axios")
|
||||
|
||||
@@ -24,17 +23,10 @@ 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()
|
||||
})
|
||||
|
||||
@@ -1186,6 +1178,25 @@ describe('#SLP TokenType1', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#generateSendOpReturn07', () => {
|
||||
it('should generate send OP_RETURN code', () => {
|
||||
// Mock UTXO.
|
||||
const tokenUtxos = [
|
||||
{
|
||||
tokenId: '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
|
||||
decimals: 8,
|
||||
tokenQty: 2
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateSendOpReturn(tokenUtxos, 1.5)
|
||||
// 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.
|
||||
@@ -1206,11 +1217,11 @@ describe('#SLP TokenType1', () => {
|
||||
tokenDocumentUrl: '',
|
||||
tokenDocumentHash: '',
|
||||
decimals: 8,
|
||||
tokenQty: 7
|
||||
tokenQty: '7'
|
||||
}
|
||||
]
|
||||
|
||||
const result = bchjs.SLP.TokenType1.generateBurnOpReturn(tokenUtxos, 1)
|
||||
const result = bchjs.SLP.TokenType1.generateBurnOpReturn(tokenUtxos, 8)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
// console.log(`result: `, result)
|
||||
|
||||
|
||||
+34
-33
@@ -497,39 +497,40 @@ describe('#SLP Utils', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw error if utxo does not have satoshis or value property.', async () => {
|
||||
try {
|
||||
const utxos = [
|
||||
{
|
||||
txid:
|
||||
'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90',
|
||||
vout: 3,
|
||||
amount: 0.00002015,
|
||||
satoshis: 2015,
|
||||
height: 594892,
|
||||
confirmations: 5
|
||||
},
|
||||
{
|
||||
txid:
|
||||
'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90',
|
||||
vout: 2,
|
||||
amount: 0.00000546,
|
||||
height: 594892,
|
||||
confirmations: 5
|
||||
}
|
||||
]
|
||||
|
||||
await uut.Utils.tokenUtxoDetails(utxos)
|
||||
|
||||
assert.equal(true, false, 'Unexpected result.')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'utxo 1 does not have a satoshis or value property',
|
||||
'Expected error message.'
|
||||
)
|
||||
}
|
||||
})
|
||||
// CT 1/9/21: This test can be removed after 2/1/21
|
||||
// it('should throw error if utxo does not have satoshis or value property.', async () => {
|
||||
// try {
|
||||
// const utxos = [
|
||||
// {
|
||||
// txid:
|
||||
// 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90',
|
||||
// vout: 3,
|
||||
// amount: 0.00002015,
|
||||
// satoshis: 2015,
|
||||
// height: 594892,
|
||||
// confirmations: 5
|
||||
// },
|
||||
// {
|
||||
// txid:
|
||||
// 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90',
|
||||
// vout: 2,
|
||||
// amount: 0.00000546,
|
||||
// height: 594892,
|
||||
// confirmations: 5
|
||||
// }
|
||||
// ]
|
||||
//
|
||||
// await uut.Utils.tokenUtxoDetails(utxos)
|
||||
//
|
||||
// assert.equal(true, false, 'Unexpected result.')
|
||||
// } catch (err) {
|
||||
// assert.include(
|
||||
// err.message,
|
||||
// 'utxo 1 does not have a satoshis or value property',
|
||||
// 'Expected error message.'
|
||||
// )
|
||||
// }
|
||||
// })
|
||||
|
||||
it('should throw error if utxo does not have txid or tx_hash property.', async () => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user