From 95789903f0b25ca4048020dbd548507b2a07854a Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Date: Tue, 14 Jul 2020 01:45:07 -0400 Subject: [PATCH] feat(endpoint): Added new /generateSendOpReturn POST endpoint --- src/routes/v3/slp.js | 55 ++++++++++++++++++++++++++ test/v3/slp.js | 92 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/src/routes/v3/slp.js b/src/routes/v3/slp.js index d7844f2..182296c 100644 --- a/src/routes/v3/slp.js +++ b/src/routes/v3/slp.js @@ -82,6 +82,7 @@ class Slp { '/transactionHistoryAllTokens/:address', _this.txsByAddressSingle ) + _this.router.post('/generateSendOpReturn', _this.generateSendOpReturn) } // DRY error handler. @@ -1609,6 +1610,60 @@ class Slp { }) } } + + // Get OP_RETURN script and outputs + async generateSendOpReturn (req, res, next) { + try { + const tokenUtxos = req.body.tokenUtxos + + const _sendQty = req.body.sendQty + const sendQty = Number(_sendQty) + + // Reject if tokenUtxos is not an array. + if (!Array.isArray(tokenUtxos)) { + res.status(400) + return res.json({ + error: 'tokenUtxos needs to be an array.' + }) + } + + // Reject if tokenUtxos array is empty. + if (!tokenUtxos.length) { + res.status(400) + return res.json({ + error: 'tokenUtxos array can not be empty.' + }) + } + + // Reject if sendQty is not an number. + if (!sendQty) { + res.status(400) + return res.json({ + error: 'sendQty must be a number.' + }) + } + + const opReturn = await _this.bchjs.SLP.TokenType1.generateSendOpReturn( + tokenUtxos, + sendQty + ) + return opReturn + } catch (err) { + wlogger.error('Error in slp.js/generateSendOpReturn().', 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 /generateSendOpReturn()' + }) + } + } } module.exports = Slp diff --git a/test/v3/slp.js b/test/v3/slp.js index de61db6..668bec4 100644 --- a/test/v3/slp.js +++ b/test/v3/slp.js @@ -787,6 +787,98 @@ describe('#SLP', () => { assert.isArray(result) }) }) + + describe('generateSendOpReturn()', () => { + const generateSendOpReturn = slpRoute.generateSendOpReturn + // Validate tokenUtxos input + it('should throw 400 if tokenUtxos is missing', async () => { + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenUtxos needs to be an array.') + }) + + it('should throw 400 if tokenUtxos is empty', async () => { + req.body.tokenUtxos = '' + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenUtxos needs to be an array.') + }) + + it('should throw 400 if tokenUtxos is not array', async () => { + req.body.tokenUtxos = 'tokenUtxos' + + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenUtxos needs to be an array.') + }) + it('should throw 400 if tokenUtxos is empty array', async () => { + req.body.tokenUtxos = [] + + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenUtxos array can not be empty.') + }) + // Validate sendQty input + it('should throw 400 if sendQty is missing', async () => { + req.body.tokenUtxos = [{}, {}, {}] + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'sendQty must be a number') + }) + + it('should throw 400 if sendQty is empty', async () => { + req.body.tokenUtxos = [{}, {}, {}] + req.body.sendQty = '' + + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'sendQty must be a number') + }) + it('should throw 400 if sendQty is not a number', async () => { + req.body.tokenUtxos = [{}, {}, {}] + req.body.sendQty = 'sendQty' + + const result = await generateSendOpReturn(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'sendQty must be a number') + }) + it('should return OP_RETURN script', async () => { + req.body.tokenUtxos = [ + { + tokenId: '0a321bff9761f28e06a268b14711274bb77617410a16807bd0437ef234a072b1', + decimals: 0, + tokenQty: 2 + } + ] + req.body.sendQty = 1.5 + + if (process.env.TEST === 'unit') { + sandbox + .stub(slpRoute.bchjs.SLP.TokenType1, 'generateSendOpReturn') + .resolves({ script: '