Merge pull request #3 from Permissionless-Software-Foundation/ct-unstable

feat(balance): Added Fulcrum balance call to REST and JSON
This commit is contained in:
Chris Troutner
2021-07-15 09:33:46 -07:00
committed by GitHub
4 changed files with 158 additions and 93 deletions
+38
View File
@@ -123,6 +123,44 @@ class FulcrumRPC {
}
}
/**
* @api {JSON} /fulcrum Balance
* @apiPermission public
* @apiName Balance
* @apiGroup JSON Fulcrum
* @apiDescription This endpoint wraps the bchjs.Electrumx.balance([]) function.
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"fulcrum","params":{ "endpoint": "balance", "addresses": ["bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"]}}
*
*/
async balance (rpcData) {
try {
// console.log('createUser rpcData: ', rpcData)
const addrs = rpcData.payload.params.addresses
const data = await this.bchjs.Electrumx.balance(addrs)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
const retObj = data
retObj.status = 200
return retObj
} catch (err) {
// console.error('Error in createUser()')
// throw err
// Return an error response
return {
success: false,
status: 422,
message: err.message,
endpoint: 'balance'
}
}
}
// TODO create deleteUser()
}
@@ -66,6 +66,44 @@ class FulcrumRESTController {
}
}
/**
* @api {post} /fulcrum/balance Balance
* @apiName Balance
* @apiGroup REST Fulcrum
* @apiDescription This endpoint returns the balance in BCH for an address.
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "addresses": ["bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"] }' localhost:5001/fulcrum/balance
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* success:true,
* data: <data>
* }
*
* @apiError UnprocessableEntity Missing required parameters
*
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 422 Unprocessable Entity
* {
* "status": 422,
* "error": "Unprocessable Entity"
* }
*/
async balance (ctx) {
try {
const addrs = ctx.request.body.addresses
const data = await _this.bchjs.Electrumx.balance(addrs)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
ctx.body = data
} catch (err) {
_this.handleError(ctx, err)
}
}
// DRY error handler
handleError (ctx, err) {
// If an HTTP status is specified by the buisiness logic, use that.
@@ -144,7 +144,7 @@ describe('#FulcrumRPC', () => {
const rpcData = jsonrpc.parse(jsonStr)
const response = await uut.transactions(rpcData)
console.log('response: ', response)
// console.log('response: ', response)
assert.equal(response.success, false)
assert.equal(response.status, 422)
@@ -153,96 +153,51 @@ describe('#FulcrumRPC', () => {
})
})
// describe('#authUser', () => {
// it('should return a JWT token if user successfully authenticates', async () => {
// // Generate the parsed data that the main router would pass to this
// // endpoint.
// const id = uid()
// const authCall = jsonrpc.request(id, 'auth', {
// endpoint: 'authUser',
// login: 'test543@test.com',
// password: 'password'
// })
// const jsonStr = JSON.stringify(authCall, null, 2)
// const rpcData = jsonrpc.parse(jsonStr)
//
// const response = await uut.authUser(rpcData)
// // console.log('response: ', response)
//
// assert.equal(response.endpoint, 'authUser')
// assert.property(response, 'userId')
// // assert.equal(response.userType, 'user')
// assert.property(response, 'userName')
// assert.property(response, 'userEmail')
// assert.property(response, 'apiToken')
// assert.equal(response.status, 200)
// assert.equal(response.success, true)
// assert.property(response, 'message')
// })
//
// it('should return an error for invalid credentials', async () => {
// // Generate the parsed data that the main router would pass to this
// // endpoint.
// const id = uid()
// const authCall = jsonrpc.request(id, 'auth', {
// endpoint: 'authUser',
// login: 'test543@test.com',
// password: 'badpassword'
// })
// const jsonStr = JSON.stringify(authCall, null, 2)
// const rpcData = jsonrpc.parse(jsonStr)
//
// // Force an error.
// sandbox
// .stub(uut.userLib, 'authUser')
// .rejects(new Error('Login credential do not match'))
//
// const response = await uut.authUser(rpcData)
// // console.log('response: ', response)
//
// assert.equal(response.success, false)
// assert.equal(response.status, 422)
// assert.equal(response.message, 'Login credential do not match')
// assert.equal(response.endpoint, 'authUser')
// })
//
// it('should throw an error if login is not provided', async () => {
// // Generate the parsed data that the main router would pass to this
// // endpoint.
// const id = uid()
// const authCall = jsonrpc.request(id, 'auth', {
// endpoint: 'authUser'
// })
// const jsonStr = JSON.stringify(authCall, null, 2)
// const rpcData = jsonrpc.parse(jsonStr)
//
// const response = await uut.authUser(rpcData)
// // console.log('response: ', response)
//
// assert.equal(response.success, false)
// assert.equal(response.status, 422)
// assert.equal(response.message, 'login must be specified')
// assert.equal(response.endpoint, 'authUser')
// })
//
// it('should throw an error if password is not provided', async () => {
// // Generate the parsed data that the main router would pass to this
// // endpoint.
// const id = uid()
// const authCall = jsonrpc.request(id, 'auth', {
// endpoint: 'authUser',
// login: 'test543@test.com'
// })
// const jsonStr = JSON.stringify(authCall, null, 2)
// const rpcData = jsonrpc.parse(jsonStr)
//
// const response = await uut.authUser(rpcData)
// // console.log('response: ', response)
//
// assert.equal(response.success, false)
// assert.equal(response.status, 422)
// assert.equal(response.message, 'password must be specified')
// assert.equal(response.endpoint, 'authUser')
// })
// })
describe('#balance', () => {
it('should return data from bchjs', async () => {
// Mock dependencies
sandbox.stub(uut.bchjs.Electrumx, 'balance').resolves({ success: true })
// Generate the parsed data that the main router would pass to this
// endpoint.
const id = uid()
const rpcCall = jsonrpc.request(id, 'fulcrum', {
endpoint: 'balance',
addresses: 'testAddr'
})
const jsonStr = JSON.stringify(rpcCall, null, 2)
const rpcData = jsonrpc.parse(jsonStr)
const response = await uut.balance(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.Electrumx, 'balance')
.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, 'fulcrum', {
endpoint: 'balance',
addresses: 'testAddr'
})
const jsonStr = JSON.stringify(rpcCall, null, 2)
const rpcData = jsonrpc.parse(jsonStr)
const response = await uut.balance(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, 'balance')
})
})
})
@@ -97,6 +97,40 @@ describe('#Fulcrum-REST-Router', () => {
})
})
describe('#balance', () => {
it('should return data from bchjs', async () => {
// Mock dependencies
sandbox.stub(uut.bchjs.Electrumx, 'balance').resolves({ success: true })
ctx.request.body = {
addresses: 'testAddr'
}
await uut.balance(ctx)
// console.log('ctx.body: ', ctx.body)
assert.equal(ctx.body.success, true)
})
it('should catch and throw an error', async () => {
try {
// Force an error
sandbox
.stub(uut.bchjs.Electrumx, 'balance')
.rejects(new Error('test error'))
ctx.request.body = {
addresses: 'testAddr'
}
await uut.balance(ctx)
} catch (err) {
// console.log('err: ', err)
assert.include(err.message, 'test error')
}
})
})
describe('#handleError', () => {
it('should pass an error message', () => {
try {