Compare commits

...
4 Commits
15 changed files with 422 additions and 162 deletions
+135 -149
View File
@@ -147,106 +147,6 @@
"to-fast-properties": "^2.0.0"
}
},
"@chris.troutner/bch-js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@chris.troutner/bch-js/-/bch-js-3.0.1.tgz",
"integrity": "sha512-XTOCFeMCBThXlGxdWsmW6OmfZBqa3XtsvFGE3hIapWfvoCUd6fSyegn9G1mXod236D3qKTW/Vk/NBwGlc7Y1YQ==",
"requires": {
"@uppy/core": "^1.10.4",
"@uppy/tus": "^1.5.12",
"apidoc": "^0.17.7",
"assert": "^2.0.0",
"axios": "^0.19.0",
"bc-bip68": "^1.0.5",
"bch-wallet-bridge.js": "github:web3bch/bch-wallet-bridge.js#master",
"bchaddrjs-slp": "^0.2.5",
"bigi": "^1.4.2",
"bignumber.js": "^9.0.0",
"bip-schnorr": "^0.3.0",
"bip21": "github:Bitcoin-com/bip21",
"bip32-utils": "github:Bitcoin-com/bip32-utils#0.13.1",
"bip38": "^2.0.2",
"bip39": "^3.0.2",
"bip66": "^1.1.5",
"bitcoincash-ops": "github:christroutner/bitcoincash-ops",
"bitcoincashjs-lib": "github:christroutner/bitcoincashjs-lib",
"bitcoinjs-message": "^2.0.0",
"bs58": "^4.0.1",
"buffer": "^5.1.0",
"cashaddrjs": "^0.3.3",
"chalk": "^2.3.0",
"clear": "0.1.0",
"coininfo": "github:Bitcoin-com/coininfo",
"commander": "^3.0.0",
"cp-file": "^7.0.0",
"ecurve": "^1.0.6",
"figlet": "^1.2.0",
"git-clone": "^0.1.0",
"ini": "^1.3.5",
"mkdirp": "^0.5.1",
"node-cmd": "^3.0.0",
"node-emoji": "^1.8.1",
"qrcode": "^1.4.1",
"randombytes": "^2.0.6",
"repl.history": "^0.1.4",
"safe-buffer": "^5.1.2",
"satoshi-bitcoin": "^1.0.4",
"slp-mdm": "0.0.6",
"slp-parser": "0.0.4",
"socket.io": "^2.1.1",
"socket.io-client": "^2.1.1",
"touch": "^3.1.0",
"wif": "^2.0.6"
},
"dependencies": {
"apidoc": {
"version": "0.17.7",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.17.7.tgz",
"integrity": "sha512-9Wf4bRPwCuWOIOxR42dDnsXnFw+rhJg5VrMQK+KmNxJwyIh30UqX6gvjjXSG6YO74MqE87F18bbQXUENK9dPGg==",
"requires": {
"apidoc-core": "~0.8.2",
"commander": "^2.19.0",
"fs-extra": "^7.0.0",
"lodash": "^4.17.10",
"markdown-it": "^8.3.1",
"winston": "^3.0.0"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}
}
},
"fs-extra": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "^4.1.6"
}
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
}
}
},
"@istanbuljs/load-nyc-config": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz",
@@ -465,6 +365,127 @@
"@types/node": ">= 8"
}
},
"@psf/bch-js": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-3.5.5.tgz",
"integrity": "sha512-bZs1p6VNDBYJPJuKuYD4h2Wsp+gt38181XlVX+2Yq8JGFOvf5ZRSrkqcd0LYvfiP8f9IA46aaAtTaLQT1KQsJw==",
"requires": {
"@uppy/core": "^1.10.4",
"@uppy/tus": "^1.5.12",
"apidoc": "^0.17.7",
"assert": "^2.0.0",
"axios": "^0.19.0",
"bc-bip68": "^1.0.5",
"bch-wallet-bridge.js": "github:web3bch/bch-wallet-bridge.js#master",
"bchaddrjs-slp": "^0.2.5",
"bigi": "^1.4.2",
"bignumber.js": "^9.0.0",
"bip-schnorr": "^0.3.0",
"bip21": "github:Bitcoin-com/bip21",
"bip32-utils": "github:Bitcoin-com/bip32-utils#0.13.1",
"bip38": "^2.0.2",
"bip39": "^3.0.2",
"bip66": "^1.1.5",
"bitcoincash-ops": "github:christroutner/bitcoincash-ops",
"bitcoincashjs-lib": "github:christroutner/bitcoincashjs-lib#master",
"bitcoinjs-message": "^2.0.0",
"bs58": "^4.0.1",
"buffer": "^5.1.0",
"cashaddrjs": "^0.3.3",
"chalk": "^2.3.0",
"clear": "0.1.0",
"coininfo": "github:Bitcoin-com/coininfo",
"commander": "^3.0.0",
"cp-file": "^7.0.0",
"ecurve": "^1.0.6",
"figlet": "^1.2.0",
"git-clone": "^0.1.0",
"ini": "^1.3.5",
"mkdirp": "^0.5.1",
"node-cmd": "^3.0.0",
"node-emoji": "^1.8.1",
"qrcode": "^1.4.1",
"randombytes": "^2.0.6",
"repl.history": "^0.1.4",
"safe-buffer": "^5.1.2",
"satoshi-bitcoin": "^1.0.4",
"slp-mdm": "0.0.6",
"slp-parser": "0.0.4",
"socket.io": "^2.1.1",
"socket.io-client": "^2.1.1",
"touch": "^3.1.0",
"wif": "^2.0.6"
},
"dependencies": {
"apidoc": {
"version": "0.17.7",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.17.7.tgz",
"integrity": "sha512-9Wf4bRPwCuWOIOxR42dDnsXnFw+rhJg5VrMQK+KmNxJwyIh30UqX6gvjjXSG6YO74MqE87F18bbQXUENK9dPGg==",
"requires": {
"apidoc-core": "~0.8.2",
"commander": "^2.19.0",
"fs-extra": "^7.0.0",
"lodash": "^4.17.10",
"markdown-it": "^8.3.1",
"winston": "^3.0.0"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}
}
},
"bitcoincashjs-lib": {
"version": "github:christroutner/bitcoincashjs-lib#715823b5d6eb3e2961e715605ad1464f3223da0b",
"from": "github:christroutner/bitcoincashjs-lib#master",
"requires": {
"bech32": "^1.1.2",
"bigi": "^1.4.0",
"bip66": "^1.1.0",
"bitcoincash-ops": "github:christroutner/bitcoincash-ops",
"bs58check": "^2.0.0",
"create-hash": "^1.1.0",
"create-hmac": "^1.1.3",
"ecurve": "^1.0.0",
"merkle-lib": "^2.0.10",
"pushdata-bitcoin": "github:Bitcoin-com/pushdata-bitcoin#1.2.1",
"randombytes": "^2.0.1",
"safe-buffer": "^5.0.1",
"typeforce": "^1.18.0",
"varuint-bitcoin": "^1.0.4",
"wif": "^2.0.1"
}
},
"fs-extra": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "^4.1.6"
}
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
}
}
},
"@semantic-release/commit-analyzer": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-7.0.0.tgz",
@@ -2289,27 +2310,6 @@
"resolved": "https://registry.npmjs.org/bitcoincashjs/-/bitcoincashjs-0.1.14.tgz",
"integrity": "sha512-x0wMVSCZ56ZQnSQ+Xim7XfS0IYiOyOwo0pdMCmR+cDNB7zRhICFuH5i3lNdLSgUw1e7Pc3FmUlC9wruQNlYMnA=="
},
"bitcoincashjs-lib": {
"version": "github:christroutner/bitcoincashjs-lib#b03ca974d4fd548cb42c7a522863e5d9be6051ef",
"from": "github:christroutner/bitcoincashjs-lib",
"requires": {
"bech32": "^1.1.2",
"bigi": "^1.4.0",
"bip66": "^1.1.0",
"bitcoincash-ops": "github:christroutner/bitcoincash-ops",
"bs58check": "^2.0.0",
"create-hash": "^1.1.0",
"create-hmac": "^1.1.3",
"ecurve": "^1.0.0",
"merkle-lib": "^2.0.10",
"pushdata-bitcoin": "github:Bitcoin-com/pushdata-bitcoin#1.2.1",
"randombytes": "^2.0.1",
"safe-buffer": "^5.0.1",
"typeforce": "^1.18.0",
"varuint-bitcoin": "^1.0.4",
"wif": "^2.0.1"
}
},
"bitcoinjs-message": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/bitcoinjs-message/-/bitcoinjs-message-2.1.0.tgz",
@@ -2324,42 +2324,28 @@
}
},
"bitcore-lib": {
"version": "8.21.0",
"resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.21.0.tgz",
"integrity": "sha512-Z1lDqSReD/Ah/n7qEsR564AlNImwYeB1MQ0fnOD6e2piNsTXQ3cSjgH93MxVARpX4LRkEev2XBnYCJ4NcYTQdQ==",
"version": "8.22.2",
"resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.22.2.tgz",
"integrity": "sha512-atl/RN7x2R/JQMaIgUzX0EQZ+I/d7fTaOoS2/5k+H5POGc2vygWZ9MWpGJi3T9Yb5jM/cT5aFsrDq8s8l6lqgQ==",
"requires": {
"bech32": "=1.1.3",
"bn.js": "=4.11.8",
"bs58": "^4.0.1",
"buffer-compare": "=1.1.1",
"elliptic": "=6.4.0",
"elliptic": "^6.5.3",
"inherits": "=2.0.1",
"lodash": "=4.17.15"
"lodash": "^4.17.20"
},
"dependencies": {
"elliptic": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
"integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
"requires": {
"bn.js": "^4.4.0",
"brorand": "^1.0.1",
"hash.js": "^1.0.0",
"hmac-drbg": "^1.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.0"
}
},
"inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
}
}
},
@@ -2404,9 +2390,9 @@
}
},
"bl": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
"integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
@@ -9081,9 +9067,9 @@
}
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"dev": true
},
"node-gyp-build": {
+1 -1
View File
@@ -28,7 +28,7 @@
"node": ">=10.15.1"
},
"dependencies": {
"@chris.troutner/bch-js": "^3.0.1",
"@psf/bch-js": "^3.5.5",
"apidoc": "^0.23.0",
"axios": "^0.19.0",
"bitcore-lib-cash": "^8.20.3",
+1 -1
View File
@@ -23,7 +23,7 @@ const router = express.Router()
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
let _this
+1 -1
View File
@@ -19,7 +19,7 @@ const config = require('../../../config')
const RouteUtils = require('../../util/route-utils')
const routeUtils = new RouteUtils()
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
let _this
+1 -1
View File
@@ -15,7 +15,7 @@ const config = require('../../../config')
const RouteUtils = require('../../util/route-utils')
const routeUtils = new RouteUtils()
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
// Use Blockbook for getting indexer data.
+1 -1
View File
@@ -17,7 +17,7 @@ const routeUtils = new RouteUtils()
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
let _this
+1 -1
View File
@@ -11,7 +11,7 @@ const express = require('express')
const router = express.Router()
// const BCHJS = require('@chris.troutner/bch-js')
// const BCHJS = require('@psf/bch-js')
// const bchjs = new BCHJS()
// let _this
+1 -1
View File
@@ -10,7 +10,7 @@ const wlogger = require('../../util/winston-logging')
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
module.exports = {
+1 -1
View File
@@ -1,6 +1,6 @@
const axios = require('axios')
const SLPSDK = require('@chris.troutner/bch-js')
const SLPSDK = require('@psf/bch-js')
const SLP = new SLPSDK()
class Slpdb {
+71 -1
View File
@@ -13,7 +13,7 @@ const Slpdb = require('./services/slpdb')
// const strftime = require('strftime')
const wlogger = require('../../util/winston-logging')
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
// Used to convert error messages to strings, to safely pass to users.
@@ -79,6 +79,7 @@ class Slp {
_this.txsByAddressSingle
)
_this.router.post('/generateSendOpReturn', _this.generateSendOpReturn)
_this.router.post('/hydrateUtxos', _this.hydrateUtxos)
}
// DRY error handler.
@@ -1519,6 +1520,75 @@ class Slp {
})
}
}
/**
* @api {post} /slp/hydrateUtxos/ hydrateUtxos
* @apiName SLP hydrateUtxos
* @apiGroup SLP
* @apiDescription Hydrate UTXO data with SLP information.
*
* Expects an array of UTXO objects as input. Returns an array of equal size.
* Returns UTXO data hydrated with token information. If the UTXO does not
* belong to a SLP transaction, it will return an isValid property set to
* false. If the UTXO is part of an SLP transaction, it will return the UTXO
* object with additional SLP information attached. An isValid property will
* be included. If its value is true, the UTXO is a valid SLP UTXO. If the
* value is null, then SLPDB has not yet processed that txid and validity has
* not been confirmed.
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/hydrateUtxos" -H "accept:application/json" -H "Content-Type: application/json" -d '{"utxos":[{"txid": "d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56","vout": 3, "value": "6816", "height": 606848, "confirmations": 13, "satoshis": 6816}, {"txid": "d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56","vout": 2, "value": "546", "height": 606848, "confirmations": 13, "satoshis": 546}]}'
*
*
*/
async hydrateUtxos (req, res, next) {
try {
const utxos = req.body.utxos
// Validate inputs
if (!Array.isArray(utxos)) {
res.status(422)
return res.json({
error: 'Input must be an array.'
})
}
if (!utxos.length) {
res.status(422)
return res.json({
error: 'Array should not be empty'
})
}
if (utxos.length > 20) {
res.status(422)
return res.json({
error: 'Array too long, max length is 20'
})
}
// Get Token Utxo Details
const details = await _this.bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log('details : ', details)
res.status(200)
return res.json({ slpUtxos: details })
} catch (err) {
wlogger.error('Error in slp.js/hydrateUtxos().', err)
// Decode the error message.
const { msg, status } = routeUtils.decodeError(err)
if (msg) {
res.status(status)
return res.json({ error: msg })
}
res.status(500)
return res.json({
error: 'Error in hydrateUtxos()'
})
}
}
}
module.exports = Slp
+1 -1
View File
@@ -12,7 +12,7 @@ const blockbook = new Blockbook()
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
// const BCHJS_TESTNET = 'https://testnet.bchjs.cash/v3/'
+1 -1
View File
@@ -16,7 +16,7 @@ const router = express.Router()
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
// Connect the route endpoints to their handler functions.
+1 -1
View File
@@ -10,7 +10,7 @@ const wlogger = require('./winston-logging')
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
const BCHJS = require('@chris.troutner/bch-js')
const BCHJS = require('@psf/bch-js')
const bchjs = new BCHJS()
// let _this
+63 -1
View File
@@ -102,7 +102,7 @@ describe('#slp', () => {
})
})
describe('generateSendOpReturn', () => {
describe('#generateSendOpReturn', () => {
it('should return OP_RETURN script', async () => {
req.body.tokenUtxos = [
{
@@ -121,4 +121,66 @@ describe('#slp', () => {
assert.isNumber(result.outputs)
})
})
describe('#hydrateUtxos', () => {
it('should return utxo details', async () => {
const utxos = [
{
txid:
'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56',
vout: 3,
value: '6816',
height: 606848,
confirmations: 13,
satoshis: 6816
},
{
txid:
'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56',
vout: 2,
value: '546',
height: 606848,
confirmations: 13,
satoshis: 546
}
]
req.body.utxos = utxos
const result = await slp.hydrateUtxos(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Test the general structure of the output.
assert.isArray(result.slpUtxos)
assert.equal(result.slpUtxos.length, 2)
// Test the non-slp UTXO.
assert.property(result.slpUtxos[0], 'txid')
assert.property(result.slpUtxos[0], 'vout')
assert.property(result.slpUtxos[0], 'value')
assert.property(result.slpUtxos[0], 'height')
assert.property(result.slpUtxos[0], 'confirmations')
assert.property(result.slpUtxos[0], 'satoshis')
assert.property(result.slpUtxos[0], 'isValid')
assert.equal(result.slpUtxos[0].isValid, false)
// Test the slp UTXO.
assert.property(result.slpUtxos[1], 'txid')
assert.property(result.slpUtxos[1], 'vout')
assert.property(result.slpUtxos[1], 'value')
assert.property(result.slpUtxos[1], 'height')
assert.property(result.slpUtxos[1], 'confirmations')
assert.property(result.slpUtxos[1], 'satoshis')
assert.property(result.slpUtxos[1], 'isValid')
assert.equal(result.slpUtxos[1].isValid, true)
assert.property(result.slpUtxos[1], 'transactionType')
assert.property(result.slpUtxos[1], 'tokenId')
assert.property(result.slpUtxos[1], 'tokenTicker')
assert.property(result.slpUtxos[1], 'tokenName')
assert.property(result.slpUtxos[1], 'tokenDocumentUrl')
assert.property(result.slpUtxos[1], 'tokenDocumentHash')
assert.property(result.slpUtxos[1], 'decimals')
assert.property(result.slpUtxos[1], 'tokenType')
assert.property(result.slpUtxos[1], 'tokenQty')
})
})
})
+142
View File
@@ -888,6 +888,148 @@ describe('#SLP', () => {
assert.isNumber(result.outputs)
})
})
describe('#hydrateUtxos', () => {
it('should throw error if input is not an array.', async () => {
req.body.utxos = 'test'
const result = await slpRoute.hydrateUtxos(req, res)
// console.log(`result: `, result)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'Input must be an array')
})
it('should throw error if Array is empty', async () => {
req.body.utxos = []
const result = await slpRoute.hydrateUtxos(req, res)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'Array should not be empty')
})
it('should throw error if Array is too long', async () => {
const utxo = {
txid:
'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90',
vout: 3,
amount: 0.00002015,
satoshis: 2015,
height: 594892,
confirmations: 5
}
const utxos = []
// Populate array with 21 utxos
for (let i = 0; i < 21; i++) {
utxos.push(utxo)
}
req.body.utxos = utxos
const result = await slpRoute.hydrateUtxos(req, res)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'Array too long, max length is 20')
})
it('should return utxo details', async () => {
const utxos = [
{
txid:
'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56',
vout: 3,
value: '6816',
height: 606848,
confirmations: 13,
satoshis: 6816
},
{
txid:
'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56',
vout: 2,
value: '546',
height: 606848,
confirmations: 13,
satoshis: 546
}
]
// Mock the external network call.
sandbox.stub(slpRoute.bchjs.SLP.Utils, 'tokenUtxoDetails').resolves([
{
txid:
'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56',
vout: 3,
value: '6816',
height: 606848,
confirmations: 13,
satoshis: 6816,
isValid: false
},
{
txid:
'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56',
vout: 2,
value: '546',
height: 606848,
confirmations: 13,
satoshis: 546,
utxoType: 'token',
transactionType: 'send',
tokenId:
'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
tokenTicker: 'TAP',
tokenName: 'Thoughts and Prayers',
tokenDocumentUrl: '',
tokenDocumentHash: '',
decimals: 0,
tokenType: 1,
tokenQty: 5,
isValid: true
}
])
req.body.utxos = utxos
const result = await slpRoute.hydrateUtxos(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Test the general structure of the output.
assert.isArray(result.slpUtxos)
assert.equal(result.slpUtxos.length, 2)
// Test the non-slp UTXO.
assert.property(result.slpUtxos[0], 'txid')
assert.property(result.slpUtxos[0], 'vout')
assert.property(result.slpUtxos[0], 'value')
assert.property(result.slpUtxos[0], 'height')
assert.property(result.slpUtxos[0], 'confirmations')
assert.property(result.slpUtxos[0], 'satoshis')
assert.property(result.slpUtxos[0], 'isValid')
assert.equal(result.slpUtxos[0].isValid, false)
// Test the slp UTXO.
assert.property(result.slpUtxos[1], 'txid')
assert.property(result.slpUtxos[1], 'vout')
assert.property(result.slpUtxos[1], 'value')
assert.property(result.slpUtxos[1], 'height')
assert.property(result.slpUtxos[1], 'confirmations')
assert.property(result.slpUtxos[1], 'satoshis')
assert.property(result.slpUtxos[1], 'isValid')
assert.equal(result.slpUtxos[1].isValid, true)
assert.property(result.slpUtxos[1], 'transactionType')
assert.property(result.slpUtxos[1], 'tokenId')
assert.property(result.slpUtxos[1], 'tokenTicker')
assert.property(result.slpUtxos[1], 'tokenName')
assert.property(result.slpUtxos[1], 'tokenDocumentUrl')
assert.property(result.slpUtxos[1], 'tokenDocumentHash')
assert.property(result.slpUtxos[1], 'decimals')
assert.property(result.slpUtxos[1], 'tokenType')
assert.property(result.slpUtxos[1], 'tokenQty')
})
})
})
/*