Pausing work on txsByAddressSingle()

This commit is contained in:
Chris Troutner
2020-05-12 09:33:29 -07:00
parent cc17916022
commit dec6aed638
4 changed files with 332 additions and 191 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
"test": "npm run lint && npm run test-v3",
"lint": "standard --env mocha --fix",
"test-v3": "export NETWORK=mainnet && nyc --reporter=text mocha --timeout 60000 test/v3/",
"test:temp": "export NETWORK=mainnet && mocha --timeout 25000 test/v3/encryption.js",
"test:temp": "export NETWORK=mainnet && mocha --timeout 25000 test/v3/slp.js",
"test:integration": "mocha test/v3/integration",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "export NETWORK=mainnet && nyc --reporter=html mocha --timeout 25000 test/v3/",
+10 -3
View File
@@ -4,12 +4,14 @@ const SLPSDK = require('@chris.troutner/bch-js')
const SLP = new SLPSDK()
class Slpdb {
async getHistoricalSlpTransactions (addressList, fromBlock) {
// Gets transaction history for all tokens for an address. Can also specify
// block height, but defaults to 0.
async getHistoricalSlpTransactions (addressList, fromBlock = 0) {
// Build SLPDB or query from addressList
const orQueryArray = []
for (const address of addressList) {
const cashAddress = SLP.Address.toCashAddress(address)
const slpAddress = SLP.Address.toSLPAddress(address)
const cashAddress = SLP.SLP.Address.toCashAddress(address)
const slpAddress = SLP.SLP.Address.toSLPAddress(address)
const cashQuery = {
'in.e.a': cashAddress.slice(12)
@@ -55,11 +57,16 @@ class Slpdb {
}
const result = await this.runQuery(query)
// console.log(`result.data: ${JSON.stringify(result.data, null, 2)}`)
let transactions = []
// Add confirmed transactions
if (result.data && result.data.c) {
transactions = transactions.concat(result.data.c)
}
// Add unconfirmed transactions
if (result.data && result.data.u) {
transactions = transactions.concat(result.data.u)
}
+254 -186
View File
@@ -64,14 +64,24 @@ class Slp {
_this.router.get('/balancesForAddress/:address', _this.balancesForAddress)
_this.router.post('/balancesForAddress', _this.balancesForAddressBulk)
_this.router.get('/balancesForToken/:tokenId', _this.balancesForTokenSingle)
_this.router.get('/balance/:address/:tokenId', _this.balancesForAddressByTokenID)
_this.router.get(
'/balance/:address/:tokenId',
_this.balancesForAddressByTokenID
)
_this.router.get('/convert/:address', _this.convertAddressSingle)
_this.router.post('/convert', _this.convertAddressBulk)
_this.router.post('/validateTxid', _this.validateBulk)
_this.router.get('/validateTxid/:txid', _this.validateSingle)
_this.router.get('/txDetails/:txid', _this.txDetails)
_this.router.get('/tokenStats/:tokenId', _this.tokenStats)
_this.router.get('/transactions/:tokenId/:address', _this.txsTokenIdAddressSingle)
_this.router.get(
'/transactions/:tokenId/:address',
_this.txsTokenIdAddressSingle
)
_this.router.get(
'/transactionHistoryAllTokens/:address',
_this.txsByAddressSingle
)
}
// DRY error handler.
@@ -102,18 +112,24 @@ class Slp {
token.tokenDetails.blockCreated = token.tokenStats.block_created
token.tokenDetails.blockLastActiveSend =
token.tokenStats.block_last_active_send
token.tokenStats.block_last_active_send
token.tokenDetails.blockLastActiveMint =
token.tokenStats.block_last_active_mint
token.tokenStats.block_last_active_mint
token.tokenDetails.txnsSinceGenesis =
token.tokenStats.qty_valid_txns_since_genesis
token.tokenDetails.validAddresses = token.tokenStats.qty_valid_token_addresses
token.tokenDetails.totalMinted = parseFloat(token.tokenStats.qty_token_minted)
token.tokenDetails.totalBurned = parseFloat(token.tokenStats.qty_token_burned)
token.tokenStats.qty_valid_txns_since_genesis
token.tokenDetails.validAddresses =
token.tokenStats.qty_valid_token_addresses
token.tokenDetails.totalMinted = parseFloat(
token.tokenStats.qty_token_minted
)
token.tokenDetails.totalBurned = parseFloat(
token.tokenStats.qty_token_burned
)
token.tokenDetails.circulatingSupply = parseFloat(
token.tokenStats.qty_token_circulating_supply
)
token.tokenDetails.mintingBatonStatus = token.tokenStats.minting_baton_status
token.tokenDetails.mintingBatonStatus =
token.tokenStats.minting_baton_status
delete token.tokenStats.block_last_active_send
delete token.tokenStats.block_last_active_mint
@@ -127,17 +143,17 @@ class Slp {
}
/**
* @api {get} /slp/list/{tokenId} List single SLP token by id.
* @apiName List single SLP token by id.
* @apiGroup SLP
* @apiDescription Returns the list single SLP token by id.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/list/259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1" -H "accept:application/json"
*
*
*/
* @api {get} /slp/list/{tokenId} List single SLP token by id.
* @apiName List single SLP token by id.
* @apiGroup SLP
* @apiDescription Returns the list single SLP token by id.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/list/259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1" -H "accept:application/json"
*
*
*/
async listSingleToken (req, res, next) {
try {
const tokenId = req.params.tokenId
@@ -160,17 +176,17 @@ class Slp {
}
/**
* @api {post} /slp/list/ List Bulk SLP token .
* @apiName List Bulk SLP token.
* @apiGroup SLP
* @apiDescription Returns the list bulk SLP token by id.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/list" -H "accept:application/json" -H "Content-Type: application/json" -d '{"tokenIds":["7380843cd1089a1a01783f86af37734dc99667a1cdc577391b5f6ea42fc1bfb4","9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0"]}'
*
*
*/
* @api {post} /slp/list/ List Bulk SLP token .
* @apiName List Bulk SLP token.
* @apiGroup SLP
* @apiDescription Returns the list bulk SLP token by id.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/list" -H "accept:application/json" -H "Content-Type: application/json" -d '{"tokenIds":["7380843cd1089a1a01783f86af37734dc99667a1cdc577391b5f6ea42fc1bfb4","9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0"]}'
*
*
*/
async listBulkToken (req, res, next) {
try {
const tokenIds = req.body.tokenIds
@@ -220,14 +236,14 @@ class Slp {
const txids = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach(token => {
tokenRes.data.t.forEach((token) => {
txids.push(token.tokenDetails.tokenIdHex)
token = _this.formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
}
tokenIds.forEach(tokenId => {
tokenIds.forEach((tokenId) => {
if (!txids.includes(tokenId)) {
formattedTokens.push({
id: tokenId,
@@ -281,14 +297,14 @@ class Slp {
const formattedTokens = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach(token => {
tokenRes.data.t.forEach((token) => {
token = _this.formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
}
let t
formattedTokens.forEach(token => {
formattedTokens.forEach((token) => {
if (token.id === tokenId) t = token
})
@@ -308,17 +324,17 @@ class Slp {
}
/**
* @api {get} /slp/balancesForAddress/{address} List SLP balance for address.
* @apiName List SLP balance for address.
* @apiGroup SLP
* @apiDescription Returns List SLP balance for address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/balancesForAddress/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
*
*
*/
* @api {get} /slp/balancesForAddress/{address} List SLP balance for address.
* @apiName List SLP balance for address.
* @apiGroup SLP
* @apiDescription Returns List SLP balance for address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/balancesForAddress/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
*
*
*/
// Retrieve token balances for all tokens for a single address.
async balancesForAddress (req, res, next) {
try {
@@ -346,7 +362,7 @@ class Slp {
res.status(400)
return res.json({
error:
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
})
}
@@ -420,7 +436,7 @@ class Slp {
const tokenIds = []
if (tokenRes.data.g.length > 0) {
tokenRes.data.g = tokenRes.data.g.map(token => {
tokenRes.data.g = tokenRes.data.g.map((token) => {
token.tokenId = token._id
tokenIds.push(token.tokenId)
token.balance = parseFloat(token.balanceString)
@@ -430,7 +446,7 @@ class Slp {
return token
})
const promises = tokenIds.map(async tokenId => {
const promises = tokenIds.map(async (tokenId) => {
const query2 = {
v: 3,
q: {
@@ -458,7 +474,6 @@ class Slp {
baseURL: url2,
headers: options.headers,
timeout: options.timeout
}
const tokenRes2 = await _this.axios.request(opt)
// console.log(`tokenRes2.data: ${JSON.stringify(tokenRes2.data, null, 2)}`)
@@ -468,8 +483,8 @@ class Slp {
const details = await _this.axios.all(promises)
tokenRes.data.g = tokenRes.data.g.map(token => {
details.forEach(detail => {
tokenRes.data.g = tokenRes.data.g.map((token) => {
details.forEach((detail) => {
if (detail.t[0].tokenDetails.tokenIdHex === token.tokenId) {
token.decimalCount = detail.t[0].tokenDetails.decimals
}
@@ -493,17 +508,17 @@ class Slp {
}
/**
* @api {post} /slp/balancesForAddress List SLP balances for an array of addresses.
* @apiName List SLP balances for an array of addresses.
* @apiGroup SLP
* @apiDescription Returns SLP balances for an array of addresses.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/balancesForAddress" -d "{\"addresses\":[\"simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57\"]}" -H "accept:application/json"
*
*
*/
* @api {post} /slp/balancesForAddress List SLP balances for an array of addresses.
* @apiName List SLP balances for an array of addresses.
* @apiGroup SLP
* @apiDescription Returns SLP balances for an array of addresses.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/balancesForAddress" -d "{\"addresses\":[\"simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57\"]}" -H "accept:application/json"
*
*
*/
async balancesForAddressBulk (req, res, next) {
try {
const addresses = req.body.addresses
@@ -554,7 +569,7 @@ class Slp {
res.status(400)
return res.json({
error:
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
})
}
}
@@ -563,7 +578,7 @@ class Slp {
// Collect an array of promises, one for each request to slpserve.
// This is a nested array of promises.
const balancesPromises = addresses.map(async address => {
const balancesPromises = addresses.map(async (address) => {
const query = {
v: 3,
q: {
@@ -626,7 +641,6 @@ class Slp {
baseURL: url,
headers: options.headers,
timeout: options.timeout
}
const tokenRes = await _this.axios.request(opt)
// console.log(`tokenRes.data: ${JSON.stringify(tokenRes.data, null, 2)}`)
@@ -634,7 +648,7 @@ class Slp {
const tokenIds = []
if (tokenRes.data.g.length > 0) {
tokenRes.data.g = tokenRes.data.g.map(token => {
tokenRes.data.g = tokenRes.data.g.map((token) => {
token.tokenId = token._id
tokenIds.push(token.tokenId)
token.balance = parseFloat(token.balanceString)
@@ -644,7 +658,7 @@ class Slp {
}
// Collect another array of promises.
const promises = tokenIds.map(async tokenId => {
const promises = tokenIds.map(async (tokenId) => {
const query2 = {
v: 3,
q: {
@@ -671,7 +685,6 @@ class Slp {
baseURL: url2,
headers: options.headers,
timeout: options.timeout
}
const tokenRes2 = await _this.axios.request(opt)
// console.log(`tokenRes2.data: ${JSON.stringify(tokenRes2.data, null, 2)}`)
@@ -682,8 +695,8 @@ class Slp {
// Wait for all the promises to resolve.
const details = await Promise.all(promises)
tokenRes.data.g = tokenRes.data.g.map(token => {
details.forEach(detail => {
tokenRes.data.g = tokenRes.data.g.map((token) => {
details.forEach((detail) => {
if (detail.t[0].tokenDetails.tokenIdHex === token.tokenId) {
token.decimalCount = detail.t[0].tokenDetails.decimals
}
@@ -710,17 +723,17 @@ class Slp {
}
/**
* @api {get} /slp/balancesForToken/{TokenId} List SLP addresses and balances for tokenId.
* @apiName List SLP addresses and balances for tokenId.
* @apiGroup SLP
* @apiDescription Returns List SLP addresses and balances for tokenId.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/balancesForToken/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
*
*
*/
* @api {get} /slp/balancesForToken/{TokenId} List SLP addresses and balances for tokenId.
* @apiName List SLP addresses and balances for tokenId.
* @apiGroup SLP
* @apiDescription Returns List SLP addresses and balances for tokenId.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/balancesForToken/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
*
*
*/
// Retrieve token balances for all addresses by single tokenId.
async balancesForTokenSingle (req, res, next) {
try {
@@ -789,7 +802,6 @@ class Slp {
baseURL: url,
headers: options.headers,
timeout: options.timeout
}
// Get data from SLPDB.
const tokenRes = await _this.axios.request(opt)
@@ -818,17 +830,17 @@ class Slp {
}
/**
* @api {get} /slp/balance/{address}/{TokenId} List single slp token balance for address.
* @apiName List single slp token balance for address.
* @apiGroup SLP
* @apiDescription Returns List single slp token balance for address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/balance/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m/1cda254d0a995c713b7955298ed246822bee487458cd9747a91d9e81d9d28125" -H "accept:application/json"
*
*
*/
* @api {get} /slp/balance/{address}/{TokenId} List single slp token balance for address.
* @apiName List single slp token balance for address.
* @apiGroup SLP
* @apiDescription Returns List single slp token balance for address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/balance/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m/1cda254d0a995c713b7955298ed246822bee487458cd9747a91d9e81d9d28125" -H "accept:application/json"
*
*
*/
// Retrieve token balances for a single token class, for a single address.
async balancesForAddressByTokenID (req, res, next) {
try {
@@ -862,7 +874,7 @@ class Slp {
res.status(400)
return res.json({
error:
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
})
}
@@ -932,7 +944,6 @@ class Slp {
baseURL: url,
headers: options.headers,
timeout: options.timeout
}
const tokenRes = await _this.axios.request(opt)
console.log(`tokenRes.data: ${JSON.stringify(tokenRes.data, null, 2)}`)
@@ -947,7 +958,7 @@ class Slp {
}
if (tokenRes.data.g.length > 0) {
tokenRes.data.g.forEach(async token => {
tokenRes.data.g.forEach(async (token) => {
if (token._id === tokenId) {
resVal = {
cashAddress: _this.bchjs.SLP.Address.toCashAddress(slpAddr),
@@ -983,17 +994,17 @@ class Slp {
}
/**
* @api {get} /slp/convert/{address} Convert address to slpAddr, cashAddr and legacy.
* @apiName Convert address to slpAddr, cashAddr and legacy.
* @apiGroup SLP
* @apiDescription Convert address to slpAddr, cashAddr and legacy.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/convert/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
*
*
*/
* @api {get} /slp/convert/{address} Convert address to slpAddr, cashAddr and legacy.
* @apiName Convert address to slpAddr, cashAddr and legacy.
* @apiGroup SLP
* @apiDescription Convert address to slpAddr, cashAddr and legacy.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/convert/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
*
*
*/
async convertAddressSingle (req, res, next) {
try {
const address = req.params.address
@@ -1013,7 +1024,9 @@ class Slp {
}
obj.slpAddress = slpAddr
obj.cashAddress = _this.bchjs.SLP.Address.toCashAddress(slpAddr)
obj.legacyAddress = _this.bchjs.SLP.Address.toLegacyAddress(obj.cashAddress)
obj.legacyAddress = _this.bchjs.SLP.Address.toLegacyAddress(
obj.cashAddress
)
res.status(200)
return res.json(obj)
@@ -1027,17 +1040,17 @@ class Slp {
}
/**
* @api {post} /slp/convert/ Convert multiple addresses to cash, legacy and simpleledger format.
* @apiName Convert multiple addresses to cash, legacy and simpleledger format.
* @apiGroup SLP
* @apiDescription Convert multiple addresses to cash, legacy and simpleledger format.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/convert" -H "accept:application/json" -H "Content-Type: application/json" -d '{"addresses":["simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l"]}'
*
*
*/
* @api {post} /slp/convert/ Convert multiple addresses to cash, legacy and simpleledger format.
* @apiName Convert multiple addresses to cash, legacy and simpleledger format.
* @apiGroup SLP
* @apiDescription Convert multiple addresses to cash, legacy and simpleledger format.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/convert" -H "accept:application/json" -H "Content-Type: application/json" -d '{"addresses":["simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l"]}'
*
*
*/
async convertAddressBulk (req, res, next) {
const addresses = req.body.addresses
@@ -1077,7 +1090,9 @@ class Slp {
}
obj.slpAddress = slpAddr
obj.cashAddress = _this.bchjs.SLP.Address.toCashAddress(slpAddr)
obj.legacyAddress = _this.bchjs.SLP.Address.toLegacyAddress(obj.cashAddress)
obj.legacyAddress = _this.bchjs.SLP.Address.toLegacyAddress(
obj.cashAddress
)
convertedAddresses.push(obj)
}
@@ -1087,17 +1102,17 @@ class Slp {
}
/**
* @api {post} /slp/validateTxid/ Validate multiple SLP transactions by txid.
* @apiName Validate multiple SLP transactions by txid.
* @apiGroup SLP
* @apiDescription Validate multiple SLP transactions by txid.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/validateTxid" -H "accept:application/json" -H "Content-Type: application/json" -d '{"txids":["f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a","fb0eeaa501a6e1acb721669c62a3f70741f48ae0fd7f4b8e1d72088785c51952"]}'
*
*
*/
* @api {post} /slp/validateTxid/ Validate multiple SLP transactions by txid.
* @apiName Validate multiple SLP transactions by txid.
* @apiGroup SLP
* @apiDescription Validate multiple SLP transactions by txid.
*
*
* @apiExample Example usage:
* curl -X POST "https://api.fullstack.cash/v3/slp/validateTxid" -H "accept:application/json" -H "Content-Type: application/json" -d '{"txids":["f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a","fb0eeaa501a6e1acb721669c62a3f70741f48ae0fd7f4b8e1d72088785c51952"]}'
*
*
*/
async validateBulk (req, res, next) {
try {
const txids = req.body.txids
@@ -1141,7 +1156,6 @@ class Slp {
baseURL: url,
headers: options.headers,
timeout: options.timeout
}
const tokenRes = await _this.axios.request(opt)
// console.log(`tokenRes.data: ${JSON.stringify(tokenRes.data, null, 2)}`)
@@ -1153,7 +1167,7 @@ class Slp {
const tokenIds = []
if (concatArray.length > 0) {
concatArray.forEach(token => {
concatArray.forEach((token) => {
tokenIds.push(token.tx.h) // txid
const validationResult = {
@@ -1171,7 +1185,7 @@ class Slp {
// If a user-provided txid doesn't exist in the data, add it with
// valid:false property.
txids.forEach(txid => {
txids.forEach((txid) => {
if (!tokenIds.includes(txid)) {
formattedTokens.push({
txid: txid,
@@ -1189,7 +1203,7 @@ class Slp {
const thisTxid = txids[i]
// Find the element that matches the current txid.
const elem = formattedTokens.filter(x => x.txid === thisTxid)
const elem = formattedTokens.filter((x) => x.txid === thisTxid)
newOutput.push(elem[0])
}
@@ -1208,17 +1222,17 @@ class Slp {
}
/**
* @api {get} /slp/validateTxid/{txid} Validate single SLP transaction by txid.
* @apiName Validate single SLP transaction by txid.
* @apiGroup SLP
* @apiDescription Validate single SLP transaction by txid.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/validateTxid/f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a" -H "accept:application/json"
*
*
*/
* @api {get} /slp/validateTxid/{txid} Validate single SLP transaction by txid.
* @apiName Validate single SLP transaction by txid.
* @apiGroup SLP
* @apiDescription Validate single SLP transaction by txid.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/validateTxid/f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a" -H "accept:application/json"
*
*
*/
async validateSingle (req, res, next) {
try {
const txid = req.params.txid
@@ -1253,7 +1267,6 @@ class Slp {
baseURL: url,
headers: options.headers,
timeout: options.timeout
}
// Get data from SLPDB.
const tokenRes = await _this.axios.request(opt)
@@ -1271,7 +1284,7 @@ class Slp {
txid: concatArray[0].tx.h,
valid: concatArray[0].slp.valid
}
if (!result.valid) result.invalidReason = concatArray[0].slp.invalidReason
if (!result.valid) { result.invalidReason = concatArray[0].slp.invalidReason }
}
res.status(200)
@@ -1290,17 +1303,17 @@ class Slp {
// }
/**
* @api {get} /slp/txDetails/{txid} SLP transaction details.
* @apiName SLP transaction details.
* @apiGroup SLP
* @apiDescription Transaction details on a token transfer.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/txDetails/8ab4ac5dea3f9024e3954ee5b61452955d659a34561f79ef62ac44e133d0980e" -H "accept:application/json"
*
*
*/
* @api {get} /slp/txDetails/{txid} SLP transaction details.
* @apiName SLP transaction details.
* @apiGroup SLP
* @apiDescription Transaction details on a token transfer.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/txDetails/8ab4ac5dea3f9024e3954ee5b61452955d659a34561f79ef62ac44e133d0980e" -H "accept:application/json"
*
*
*/
async txDetails (req, res, next) {
try {
// Validate input parameter
@@ -1336,7 +1349,6 @@ class Slp {
baseURL: url,
headers: options.headers,
timeout: options.timeout
}
// Get token data from SLPDB
const tokenRes = await _this.axios.request(opt)
@@ -1353,7 +1365,10 @@ class Slp {
// Get information on the transaction from Insight API.
// const retData = await transactions.transactionsFromInsight(txid)
const retData = await _this.rawTransactions.getRawTransactionsFromNode(txid, true)
const retData = await _this.rawTransactions.getRawTransactionsFromNode(
txid,
true
)
// console.log(`retData: ${JSON.stringify(retData, null, 2)}`)
// Return both the tx data from Insight and the formatted token information.
@@ -1378,17 +1393,17 @@ class Slp {
}
/**
* @api {get} /slp/tokenStats/{tokenId} List stats for a single slp token.
* @apiName List stats for a single slp token.
* @apiGroup SLP
* @apiDescription Return list stats for a single slp token.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/tokenStats/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
*
*
*/
* @api {get} /slp/tokenStats/{tokenId} List stats for a single slp token.
* @apiName List stats for a single slp token.
* @apiGroup SLP
* @apiDescription Return list stats for a single slp token.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/tokenStats/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
*
*
*/
async tokenStats (req, res, next) {
const tokenId = req.params.tokenId
if (!tokenId || tokenId === '') {
@@ -1431,7 +1446,7 @@ class Slp {
const formattedTokens = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach(token => {
tokenRes.data.t.forEach((token) => {
token = _this.formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
@@ -1447,17 +1462,17 @@ class Slp {
}
/**
* @api {get} /slp/transactions/{tokenId}/{address} SLP transactions by tokenId and address.
* @apiName SLP transactions by tokenId and address.
* @apiGroup SLP
* @apiDescription Transactions by tokenId and address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/transactions/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0/simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l" -H "accept:application/json"
*
*
*/
* @api {get} /slp/transactions/{tokenId}/{address} SLP transactions by tokenId and address.
* @apiName SLP transactions by tokenId and address.
* @apiGroup SLP
* @apiDescription Transactions by tokenId and address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/slp/transactions/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0/simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l" -H "accept:application/json"
*
*
*/
// Retrieve transactions by tokenId and address.
async txsTokenIdAddressSingle (req, res, next) {
try {
@@ -1558,7 +1573,7 @@ class Slp {
const tokenOutputs = transaction.slp.detail.outputs
const sendOutputs = ['0']
tokenOutputs.map(x => {
tokenOutputs.map((x) => {
const string = parseFloat(x.amount) * 100000000
sendOutputs.push(string.toString())
})
@@ -1575,6 +1590,59 @@ class Slp {
return obj
}
// Retrieve transactions by address.
async txsByAddressSingle (req, res, next) {
try {
// Validate the input data.
const address = req.params.address
if (!address || address === '') {
res.status(400)
return res.json({ error: 'address can not be empty' })
}
// Ensure the input is a valid BCH address.
try {
_this.bchjs.SLP.Address.toCashAddress(address)
} catch (err) {
res.status(400)
return res.json({
error: `Invalid BCH address. Double check your address is valid: ${address}`
})
}
// Ensure it is using the correct network.
const cashAddr = _this.bchjs.SLP.Address.toCashAddress(address)
const networkIsValid = routeUtils.validateNetwork(cashAddr)
if (!networkIsValid) {
res.status(400)
return res.json({
error: 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
})
}
const transactions = await _this.slpdb.getHistoricalSlpTransactions([
address
])
res.status(200)
return res.json(transactions)
} catch (err) {
wlogger.error('Error in slp.ts/txsByAddressSingle().', 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 /transactionHistoryAllTokens/:address: ${err.message}`
})
}
}
}
module.exports = Slp
+67 -1
View File
@@ -68,7 +68,7 @@ describe('#SLP', () => {
res = mockRes
// Explicitly reset the parmas and body.
// req.params = {}
req.params = {}
req.body = {}
req.query = {}
req.locals = {}
@@ -774,6 +774,72 @@ describe('#SLP', () => {
)
})
})
describe('txsByAddressSingle()', () => {
const txsByAddressSingle = slpRoute.txsByAddressSingle
it('should throw 400 if address is missing', async () => {
const result = await txsByAddressSingle(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'address can not be empty')
})
it('should throw 400 if address is empty', async () => {
req.params.address = ''
const result = await txsByAddressSingle(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'address can not be empty')
})
it('should throw 400 if address is invalid', async () => {
req.params.address = 'badAddress'
const result = await txsByAddressSingle(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'Invalid BCH address.')
})
it('should throw 400 if address network mismatch', async () => {
req.params.address =
'slptest:qr83cu3p7yg9yac7qthwm0nul2ev2kukvsqmes3vl0'
const result = await txsByAddressSingle(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'Invalid')
})
it('should get tx history', async () => {
// if (process.env.TEST === "unit") {
// // nock(`${process.env.SLPDB_URL}`)
// // .get(uri => uri.includes("/"))
// // .reply(200, {
// // c: mockData.mockTransactions
// // })
// slpRoute.
// }
// req.params.address = 'simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk'
req.params.address = 'simpleledger:qz4guf2k3p4r3t4tph0wwgyfq4p628lr2c0cvqplza'
const result = await slpRoute.txsByAddressSingle(req, res)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
// for(let i=0; i < result.length; i++) {
// const entry = result[i]
//
// }
assert.isArray(result)
})
})
})
/*