mirror of
https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service.git
synced 2026-09-21 16:52:03 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62ef3e0a93 | ||
|
|
c9ab4b5ef8 | ||
|
|
f338f26593 | ||
|
|
dc302066f0 | ||
|
|
fe5c95078b | ||
|
|
c21554008c | ||
|
|
e2a900d3a0 | ||
|
|
c870b54cae | ||
|
|
f022951680 | ||
|
|
942a8f20ec | ||
|
|
683c1e4b2b | ||
|
|
953690baa5 |
+1
-1
@@ -1,5 +1,5 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2021 Permissionless Software Foundation
|
||||
Copyright (c) 2022 Permissionless Software Foundation
|
||||
|
||||
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:
|
||||
|
||||
|
||||
Generated
+40
-15
@@ -9,7 +9,7 @@
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@psf/bch-js": "6.4.5",
|
||||
"@psf/bch-js": "6.5.7",
|
||||
"axios": "0.27.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"glob": "7.1.6",
|
||||
@@ -1445,14 +1445,15 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@psf/bch-js": {
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-6.4.5.tgz",
|
||||
"integrity": "sha512-sH72zbJJI5oe9EUMczFQb0jCaNQb8rc3/86E6xXKl3325HCwBqE80BX7JFvZ97Qv1gGxwp/3WROp59v6Dz2NKA==",
|
||||
"version": "6.5.7",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fbch-js/-/bch-js-6.5.7.tgz",
|
||||
"integrity": "sha512-V9UweiRCCU4UzM51Ct2Szhpv6V0B686t5ZjMHNkPu8zyJ9+H7mQfteeQECHK5j38QHvLchfUOif5WWQxP6GRVQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chris.troutner/bip32-utils": "1.0.5",
|
||||
"@psf/bip21": "2.0.1",
|
||||
"@psf/bitcoincash-ops": "2.0.0",
|
||||
"@psf/bitcoincashjs-lib": "4.0.2",
|
||||
"@psf/bitcoincashjs-lib": "4.0.3",
|
||||
"@psf/coininfo": "4.0.0",
|
||||
"axios": "0.26.1",
|
||||
"bc-bip68": "1.0.5",
|
||||
@@ -1491,10 +1492,14 @@
|
||||
},
|
||||
"node_modules/@psf/bitcoincash-ops": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fbitcoincash-ops/-/bitcoincash-ops-2.0.0.tgz",
|
||||
"integrity": "sha512-M3PWqRpeJq6rli2NqWGbas76z9TrdGOmNuDFACBWBMctPucEAsFQY2AmyFHRSa7hEwythwvrPh9AG/n6ehmEog==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@psf/bitcoincashjs-lib": {
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.3",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fbitcoincashjs-lib/-/bitcoincashjs-lib-4.0.3.tgz",
|
||||
"integrity": "sha512-sJYi7jYUqR7S+Z8TjN3W/5Lcju7xcIBxYLhIEpnOF+jR9kMt0ftpVjQBt8vVsJZUD8ArL9bf59oDETjdOUcdGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@psf/bitcoincash-ops": "^2.0.0",
|
||||
@@ -1526,6 +1531,8 @@
|
||||
},
|
||||
"node_modules/@psf/pushdata-bitcoin": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fpushdata-bitcoin/-/pushdata-bitcoin-1.2.2.tgz",
|
||||
"integrity": "sha512-e1qkZLJFU6Ldg7TMBgSkiR5U1NfpRgSIr2ppk8BeED/Q9wUc9DEVAjXfPMD65xgXdqnlyFEtLbpPMWwyydMVUQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@psf/bitcoincash-ops": "^2.0.0"
|
||||
@@ -2928,6 +2935,8 @@
|
||||
},
|
||||
"node_modules/bech32": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "http://94.130.170.209:4873/bech32/-/bech32-1.1.4.tgz",
|
||||
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
@@ -11040,6 +11049,8 @@
|
||||
},
|
||||
"node_modules/merkle-lib": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "http://94.130.170.209:4873/merkle-lib/-/merkle-lib-2.0.10.tgz",
|
||||
"integrity": "sha1-grjbrnXieneFOItz+ddyXQ9vMyY=",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/methods": {
|
||||
@@ -19026,6 +19037,8 @@
|
||||
},
|
||||
"node_modules/typeforce": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "http://94.130.170.209:4873/typeforce/-/typeforce-1.18.0.tgz",
|
||||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/uc.micro": {
|
||||
@@ -20957,14 +20970,14 @@
|
||||
"version": "1.1.0"
|
||||
},
|
||||
"@psf/bch-js": {
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-6.4.5.tgz",
|
||||
"integrity": "sha512-sH72zbJJI5oe9EUMczFQb0jCaNQb8rc3/86E6xXKl3325HCwBqE80BX7JFvZ97Qv1gGxwp/3WROp59v6Dz2NKA==",
|
||||
"version": "6.5.7",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fbch-js/-/bch-js-6.5.7.tgz",
|
||||
"integrity": "sha512-V9UweiRCCU4UzM51Ct2Szhpv6V0B686t5ZjMHNkPu8zyJ9+H7mQfteeQECHK5j38QHvLchfUOif5WWQxP6GRVQ==",
|
||||
"requires": {
|
||||
"@chris.troutner/bip32-utils": "1.0.5",
|
||||
"@psf/bip21": "2.0.1",
|
||||
"@psf/bitcoincash-ops": "2.0.0",
|
||||
"@psf/bitcoincashjs-lib": "4.0.2",
|
||||
"@psf/bitcoincashjs-lib": "4.0.3",
|
||||
"@psf/coininfo": "4.0.0",
|
||||
"axios": "0.26.1",
|
||||
"bc-bip68": "1.0.5",
|
||||
@@ -21002,10 +21015,14 @@
|
||||
}
|
||||
},
|
||||
"@psf/bitcoincash-ops": {
|
||||
"version": "2.0.0"
|
||||
"version": "2.0.0",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fbitcoincash-ops/-/bitcoincash-ops-2.0.0.tgz",
|
||||
"integrity": "sha512-M3PWqRpeJq6rli2NqWGbas76z9TrdGOmNuDFACBWBMctPucEAsFQY2AmyFHRSa7hEwythwvrPh9AG/n6ehmEog=="
|
||||
},
|
||||
"@psf/bitcoincashjs-lib": {
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.3",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fbitcoincashjs-lib/-/bitcoincashjs-lib-4.0.3.tgz",
|
||||
"integrity": "sha512-sJYi7jYUqR7S+Z8TjN3W/5Lcju7xcIBxYLhIEpnOF+jR9kMt0ftpVjQBt8vVsJZUD8ArL9bf59oDETjdOUcdGQ==",
|
||||
"requires": {
|
||||
"@psf/bitcoincash-ops": "^2.0.0",
|
||||
"@psf/pushdata-bitcoin": "^1.2.2",
|
||||
@@ -21032,6 +21049,8 @@
|
||||
},
|
||||
"@psf/pushdata-bitcoin": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "http://94.130.170.209:4873/@psf%2fpushdata-bitcoin/-/pushdata-bitcoin-1.2.2.tgz",
|
||||
"integrity": "sha512-e1qkZLJFU6Ldg7TMBgSkiR5U1NfpRgSIr2ppk8BeED/Q9wUc9DEVAjXfPMD65xgXdqnlyFEtLbpPMWwyydMVUQ==",
|
||||
"requires": {
|
||||
"@psf/bitcoincash-ops": "^2.0.0"
|
||||
}
|
||||
@@ -22066,7 +22085,9 @@
|
||||
"version": "2.4.3"
|
||||
},
|
||||
"bech32": {
|
||||
"version": "1.1.4"
|
||||
"version": "1.1.4",
|
||||
"resolved": "http://94.130.170.209:4873/bech32/-/bech32-1.1.4.tgz",
|
||||
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.2",
|
||||
@@ -27836,7 +27857,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"merkle-lib": {
|
||||
"version": "2.0.10"
|
||||
"version": "2.0.10",
|
||||
"resolved": "http://94.130.170.209:4873/merkle-lib/-/merkle-lib-2.0.10.tgz",
|
||||
"integrity": "sha1-grjbrnXieneFOItz+ddyXQ9vMyY="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2"
|
||||
@@ -33283,7 +33306,9 @@
|
||||
}
|
||||
},
|
||||
"typeforce": {
|
||||
"version": "1.18.0"
|
||||
"version": "1.18.0",
|
||||
"resolved": "http://94.130.170.209:4873/typeforce/-/typeforce-1.18.0.tgz",
|
||||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||
},
|
||||
"uc.micro": {
|
||||
"version": "1.0.6",
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"repository": "Permissionless-Software-Foundation/ipfs-bch-wallet-service",
|
||||
"dependencies": {
|
||||
"@psf/bch-js": "6.4.5",
|
||||
"@psf/bch-js": "6.5.7",
|
||||
"axios": "0.27.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"glob": "7.1.6",
|
||||
|
||||
@@ -60,6 +60,10 @@ class BCHRPC {
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.utxos(rpcData)
|
||||
|
||||
case 'utxosBulk':
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.utxosBulk(rpcData)
|
||||
|
||||
case 'broadcast':
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.broadcast(rpcData)
|
||||
@@ -79,6 +83,10 @@ class BCHRPC {
|
||||
case 'getTokenData':
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.getTokenData(rpcData)
|
||||
|
||||
case 'getTokenData2':
|
||||
await this.rateLimit.limiter(rpcData.from)
|
||||
return await this.getTokenData2(rpcData)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error in BCHRPC/rpcRouter()')
|
||||
@@ -362,6 +370,142 @@ class BCHRPC {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {JSON} /bch UTXOs Bulk
|
||||
* @apiPermission public
|
||||
* @apiName UTXOs Bulk
|
||||
* @apiGroup JSON BCH
|
||||
* @apiDescription This endpoint provides the same data as as the utxos
|
||||
* endpoint, but it allows retrieval of UTXOs for up to 20 addresses at
|
||||
* a time. This reduces the number of JSON RPC calls, and is very handy
|
||||
* for HD wallets that need to quickly scan a lot of addresses.
|
||||
*
|
||||
* Given an array of addresses, this endpoint will return an object
|
||||
* with the following properties
|
||||
*
|
||||
* - jsonrpc: "" - jsonrpc version
|
||||
* - id: "" - jsonrpc id
|
||||
* - result: {} - Result of the request with the RPC information
|
||||
* - method: "" - Method used in the request
|
||||
* - receiver: "" - Receiver address
|
||||
* - value: [] - Final result value of the request
|
||||
* - address: "" - the address these UTXOs are associated with
|
||||
* - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
|
||||
* - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
|
||||
* not spent, to be safe.
|
||||
* - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
|
||||
* - type1: {}
|
||||
* - tokens: [] - SLP token Type 1 tokens.
|
||||
* - mintBatons: [] - SLP token Type 1 mint batons.
|
||||
* - nft: {}
|
||||
* - tokens: [] - NFT tokens
|
||||
* - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
|
||||
* - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "utxos", "address": "bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"}}
|
||||
*
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
*
|
||||
* {
|
||||
* "jsonrpc":"2.0",
|
||||
* "id":"555",
|
||||
* "result":{
|
||||
* "method":"bch",
|
||||
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
|
||||
* "value":[
|
||||
* {
|
||||
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj",
|
||||
* "bchUtxos":[
|
||||
* {
|
||||
* "height":631219,
|
||||
* "tx_hash":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f",
|
||||
* "tx_pos":0,
|
||||
* "value":1000,
|
||||
* "txid":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f",
|
||||
* "vout":0,
|
||||
* "isValid":false
|
||||
* }
|
||||
* ],
|
||||
* "nullUtxos":[
|
||||
*
|
||||
* ],
|
||||
* "slpUtxos":{
|
||||
* "type1":{
|
||||
* "mintBatons":[
|
||||
*
|
||||
* ],
|
||||
* "tokens":[
|
||||
*
|
||||
* ]
|
||||
* },
|
||||
* "nft":{
|
||||
* "groupMintBatons":[
|
||||
*
|
||||
* ],
|
||||
* "groupTokens":[
|
||||
*
|
||||
* ],
|
||||
* "tokens":[
|
||||
*
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
async utxosBulk (rpcData) {
|
||||
try {
|
||||
// console.log('createUser rpcData: ', rpcData)
|
||||
|
||||
const addrs = rpcData.payload.params.addresses
|
||||
// console.log('addr: ', addr)
|
||||
|
||||
// Input validation
|
||||
if (!Array.isArray(addrs)) {
|
||||
throw new Error('addresses parameter must be an array')
|
||||
}
|
||||
if (addrs.length > 20) {
|
||||
throw new Error('addresses parameter must not exceed 20 elements')
|
||||
}
|
||||
|
||||
const result = []
|
||||
for (let i = 0; i < addrs.length; i++) {
|
||||
const thisAddr = addrs[i]
|
||||
|
||||
const data = await this.bchjs.Utxo.get(thisAddr)
|
||||
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
||||
|
||||
result.push({
|
||||
address: thisAddr,
|
||||
utxos: data
|
||||
})
|
||||
}
|
||||
|
||||
const retObj = {}
|
||||
retObj.status = 200
|
||||
retObj.success = true
|
||||
retObj.data = result
|
||||
|
||||
return retObj
|
||||
} catch (err) {
|
||||
console.error('Error in JSON RPC BCH utxosBulk()')
|
||||
console.error('Error in JSON RPC utxosBulk(): ', err)
|
||||
// throw err
|
||||
|
||||
// Return an error response
|
||||
return {
|
||||
success: false,
|
||||
status: 422,
|
||||
message: err.message,
|
||||
endpoint: 'utxosBulk'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {JSON} /bch Broadcast
|
||||
* @apiPermission public
|
||||
@@ -788,6 +932,68 @@ class BCHRPC {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {JSON} /bch getTokenData2
|
||||
* @apiPermission public
|
||||
* @apiName getTokenData2
|
||||
* @apiGroup JSON BCH
|
||||
* @apiDescription Get token icon and other media
|
||||
*
|
||||
* Get the icon for a token, given it's token ID.
|
||||
* This function expects a string input of a token ID property.
|
||||
* This function returns an object with a tokenIcon property that contains
|
||||
* the URL to the icon.
|
||||
*
|
||||
* The output object always have these properties:
|
||||
* - tokenIcon: A url to the token icon, if it exists.
|
||||
* - tokenStats: Data about the token from psf-slp-indexer.
|
||||
* - optimizedTokenIcon: An alternative, potentially more optimal, url to the token icon, if it exists.
|
||||
* - iconRepoCompatible: true if the token icon is available via token.bch.sx
|
||||
* - ps002Compatible: true if the token icon is compatible with PS007 specification.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "getTokenData2", "tokenId": "c85042ab08a2099f27de880a30f9a42874202751d834c42717a20801a00aab0d", "withTxHistory": true }}
|
||||
*
|
||||
*/
|
||||
async getTokenData2 (rpcData) {
|
||||
try {
|
||||
// console.log('createUser rpcData: ', rpcData)
|
||||
|
||||
const tokenId = rpcData.payload.params.tokenId
|
||||
// console.log('tokenId: ', tokenId)
|
||||
|
||||
const updateCache = rpcData.payload.params.updateCache
|
||||
|
||||
const tokenData = await this.bchjs.PsfSlpIndexer.getTokenData2(tokenId, updateCache)
|
||||
|
||||
const retObj = {
|
||||
success: true,
|
||||
status: 200,
|
||||
endpoint: 'getTokenData2',
|
||||
tokenData
|
||||
}
|
||||
// retObj.status = 200
|
||||
|
||||
return retObj
|
||||
} catch (err) {
|
||||
console.error('Error in JSON RPC BCH utxoIsValid()')
|
||||
|
||||
// Handle different error formats.
|
||||
let error = err
|
||||
if (err.error && typeof err.error === 'string') {
|
||||
error = new Error(err.error)
|
||||
}
|
||||
|
||||
// Return an error response
|
||||
return {
|
||||
success: false,
|
||||
status: 422,
|
||||
message: error.message,
|
||||
endpoint: 'getTokenData2'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BCHRPC
|
||||
|
||||
@@ -118,6 +118,25 @@ describe('#BCHRPC', () => {
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should route to the utxosBulk method', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'utxosBulk').resolves(true)
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const txCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxosBulk'
|
||||
})
|
||||
const jsonStr = JSON.stringify(txCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.bchRouter(rpcData)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should route to the broadcast method', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'broadcast').resolves(true)
|
||||
@@ -175,6 +194,63 @@ describe('#BCHRPC', () => {
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should route to the utxoIsValid method', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'utxoIsValid').resolves(true)
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxoIsValid'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.bchRouter(rpcData)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should route to the getTokenData method', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'getTokenData').resolves(true)
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'getTokenData'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.bchRouter(rpcData)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should route to the getTokenData2 method', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'getTokenData2').resolves(true)
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'getTokenData2'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
rpcData.from = 'Origin request'
|
||||
|
||||
const result = await uut.bchRouter(rpcData)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should return 500 status on routing issue', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'txHistory').rejects(new Error('test error'))
|
||||
@@ -301,7 +377,7 @@ describe('#BCHRPC', () => {
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxos',
|
||||
addresses: 'testAddr'
|
||||
address: 'testAddr'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
@@ -322,7 +398,7 @@ describe('#BCHRPC', () => {
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxos',
|
||||
addresses: 'testAddr'
|
||||
address: 'testAddr'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
@@ -337,6 +413,98 @@ describe('#BCHRPC', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#utxosBulk', () => {
|
||||
it('should return UTXO data from bchjs for multiple addresses', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut.bchjs.Utxo, 'get').resolves({ success: true })
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxosBulk',
|
||||
addresses: ['testAddr1', 'testAddr2']
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
|
||||
const response = await uut.utxosBulk(rpcData)
|
||||
// console.log('response: ', response)
|
||||
|
||||
assert.equal(response.success, true)
|
||||
assert.equal(response.status, 200)
|
||||
})
|
||||
|
||||
it('should return an error for invalid address', async () => {
|
||||
// Force an error
|
||||
sandbox.stub(uut.bchjs.Utxo, 'get').rejects(new Error('Invalid address'))
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxosBulk',
|
||||
addresses: ['testAddr1', 'testAddr2']
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
|
||||
const response = await uut.utxosBulk(rpcData)
|
||||
// console.log('response: ', response)
|
||||
|
||||
assert.equal(response.success, false)
|
||||
assert.equal(response.status, 422)
|
||||
assert.equal(response.message, 'Invalid address')
|
||||
assert.equal(response.endpoint, 'utxosBulk')
|
||||
})
|
||||
|
||||
it('should throw error if input is not an array', async () => {
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxosBulk',
|
||||
addresses: 'singleAddress'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
|
||||
const response = await uut.utxosBulk(rpcData)
|
||||
// console.log('response: ', response)
|
||||
|
||||
assert.equal(response.success, false)
|
||||
assert.equal(response.status, 422)
|
||||
assert.equal(response.message, 'addresses parameter must be an array')
|
||||
assert.equal(response.endpoint, 'utxosBulk')
|
||||
})
|
||||
|
||||
it('should throw error if input array is larger than 20 elements', async () => {
|
||||
// Generate an array larger than 20 elements
|
||||
const inputArray = []
|
||||
for (let i = 0; i < 25; i++) {
|
||||
inputArray.push(i)
|
||||
}
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'utxosBulk',
|
||||
addresses: inputArray
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
|
||||
const response = await uut.utxosBulk(rpcData)
|
||||
// console.log('response: ', response)
|
||||
|
||||
assert.equal(response.success, false)
|
||||
assert.equal(response.status, 422)
|
||||
assert.equal(response.message, 'addresses parameter must not exceed 20 elements')
|
||||
assert.equal(response.endpoint, 'utxosBulk')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#broadcast', () => {
|
||||
it('should return data from bchjs', async () => {
|
||||
// Mock dependencies
|
||||
@@ -385,6 +553,32 @@ describe('#BCHRPC', () => {
|
||||
assert.equal(response.message, 'Invalid data')
|
||||
assert.equal(response.endpoint, 'broadcast')
|
||||
})
|
||||
|
||||
it('should return an error if full node returns a string error', async () => {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.bchjs.RawTransactions, 'sendRawTransaction')
|
||||
// .rejects(new Error('Invalid data'))
|
||||
.rejects({ error: 'Invalid data' })
|
||||
|
||||
// Generate the parsed data that the main router would pass to this
|
||||
// endpoint.
|
||||
const id = uid()
|
||||
const rpcCall = jsonrpc.request(id, 'bch', {
|
||||
endpoint: 'broadcast',
|
||||
hex: 'testHex'
|
||||
})
|
||||
const jsonStr = JSON.stringify(rpcCall, null, 2)
|
||||
const rpcData = jsonrpc.parse(jsonStr)
|
||||
|
||||
const response = await uut.broadcast(rpcData)
|
||||
// console.log('response: ', response)
|
||||
|
||||
assert.equal(response.success, false)
|
||||
assert.equal(response.status, 422)
|
||||
assert.equal(response.message, 'Invalid data')
|
||||
assert.equal(response.endpoint, 'broadcast')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#txData', () => {
|
||||
@@ -568,7 +762,8 @@ describe('#BCHRPC', () => {
|
||||
// Mock dependencies
|
||||
sandbox
|
||||
.stub(uut.bchjs.Utxo, 'isValid')
|
||||
.rejects(new Error('test error'))
|
||||
// .rejects(new Error('test error'))
|
||||
.rejects({ error: 'test error' })
|
||||
|
||||
const rpcData = {
|
||||
payload: {
|
||||
@@ -619,7 +814,8 @@ describe('#BCHRPC', () => {
|
||||
// Mock dependencies
|
||||
sandbox
|
||||
.stub(uut.bchjs.PsfSlpIndexer, 'getTokenData')
|
||||
.rejects(new Error('test error'))
|
||||
// .rejects(new Error('test error'))
|
||||
.rejects({ error: 'test error' })
|
||||
|
||||
const rpcData = {
|
||||
payload: {
|
||||
@@ -638,4 +834,53 @@ describe('#BCHRPC', () => {
|
||||
assert.equal(result.endpoint, 'getTokenData')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTokenData2', () => {
|
||||
it('should return data from PsfSlpIndexer.getTokenData2()', async () => {
|
||||
// Mock dependencies
|
||||
sandbox
|
||||
.stub(uut.bchjs.PsfSlpIndexer, 'getTokenData2')
|
||||
.resolves({ a: 'b' })
|
||||
|
||||
const rpcData = {
|
||||
payload: {
|
||||
params: {
|
||||
tokenId: 'c85042ab08a2099f27de880a30f9a42874202751d834c42717a20801a00aab0d'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await uut.getTokenData2(rpcData)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.equal(result.success, true)
|
||||
assert.equal(result.status, 200)
|
||||
assert.equal(result.endpoint, 'getTokenData2')
|
||||
assert.property(result, 'tokenData')
|
||||
})
|
||||
|
||||
it('should catch and return errors', async () => {
|
||||
// Mock dependencies
|
||||
sandbox
|
||||
.stub(uut.bchjs.PsfSlpIndexer, 'getTokenData2')
|
||||
// .rejects(new Error('test error'))
|
||||
.rejects({ error: 'test error' })
|
||||
|
||||
const rpcData = {
|
||||
payload: {
|
||||
params: {
|
||||
tokenId: 'c85042ab08a2099f27de880a30f9a42874202751d834c42717a20801a00aab0d'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await uut.getTokenData2(rpcData)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.equal(result.success, false)
|
||||
assert.equal(result.status, 422)
|
||||
assert.equal(result.message, 'test error')
|
||||
assert.equal(result.endpoint, 'getTokenData2')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -55,6 +55,28 @@ describe('#server', () => {
|
||||
|
||||
// Not throwing an error is a success
|
||||
})
|
||||
|
||||
it('should warn if user admin can not be created', async () => {
|
||||
// Mock dependencies and force desired code path
|
||||
sandbox.stub(uut.mongoose, 'connect').resolves()
|
||||
sandbox.stub(uut.controllers, 'initAdapters').resolves()
|
||||
sandbox.stub(uut.controllers, 'initUseCases').resolves()
|
||||
sandbox.stub(uut.controllers, 'attachRESTControllers').resolves()
|
||||
sandbox.stub(uut.adminLib, 'createSystemUser').rejects('test error')
|
||||
sandbox.stub(uut.controllers, 'attachControllers').resolves()
|
||||
uut.config.env = 'dev'
|
||||
|
||||
const result = await uut.startServer()
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'env')
|
||||
|
||||
// Turn off the server.
|
||||
uut.server.close()
|
||||
|
||||
// Restor config env
|
||||
uut.config.env = 'test'
|
||||
})
|
||||
})
|
||||
|
||||
describe('#sleep', () => {
|
||||
|
||||
@@ -89,7 +89,8 @@ const bchjs = {
|
||||
chunk100: () => {}
|
||||
},
|
||||
PsfSlpIndexer: {
|
||||
getTokenData: () => {}
|
||||
getTokenData: () => {},
|
||||
getTokenData2: () => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user