diff --git a/src/slp/tokentype1.js b/src/slp/tokentype1.js index 57c18fa..5302289 100644 --- a/src/slp/tokentype1.js +++ b/src/slp/tokentype1.js @@ -32,6 +32,93 @@ class TokenType1 { * - outputs: an integer with a value of 1 or 2. If 2, indicates there needs to be an extra output to send token change. */ generateSendOpReturn(tokenUtxos, sendQty) { + try { + const tokenId = tokenUtxos[0].tokenId + const decimals = tokenUtxos[0].decimals + + // Calculate the total amount of tokens owned by the wallet. + let totalTokens = 0 + for (let i = 0; i < tokenUtxos.length; i++) + totalTokens += tokenUtxos[i].tokenQty + + const change = totalTokens - sendQty + // console.log(`change: ${change}`) + + let script + let outputs = 1 + + // The normal case, when there is token change to return to sender. + if (change > 0) { + outputs = 2 + + let baseQty = new BigNumber(sendQty).times(10 ** decimals) + baseQty = baseQty.absoluteValue() + baseQty = Math.floor(baseQty) + let baseQtyHex = baseQty.toString(16) + baseQtyHex = baseQtyHex.padStart(16, "0") + + let baseChange = new BigNumber(change).times(10 ** decimals) + baseChange = baseChange.absoluteValue() + baseChange = Math.floor(baseChange) + // console.log(`baseChange: ${baseChange.toString()}`) + + let baseChangeHex = baseChange.toString(16) + baseChangeHex = baseChangeHex.padStart(16, "0") + // console.log(`baseChangeHex padded: ${baseChangeHex}`) + + script = [ + this.Script.opcodes.OP_RETURN, + Buffer.from("534c5000", "hex"), + //BITBOX.Script.opcodes.OP_1, + Buffer.from("01", "hex"), + Buffer.from(`SEND`), + Buffer.from(tokenId, "hex"), + Buffer.from(baseQtyHex, "hex"), + Buffer.from(baseChangeHex, "hex") + ] + } else { + // Corner case, when there is no token change to send back. + + let baseQty = new BigNumber(sendQty).times(10 ** decimals) + baseQty = baseQty.absoluteValue() + baseQty = Math.floor(baseQty) + let baseQtyHex = baseQty.toString(16) + baseQtyHex = baseQtyHex.padStart(16, "0") + + // console.log(`baseQty: ${baseQty.toString()}`) + + script = [ + this.Script.opcodes.OP_RETURN, + Buffer.from("534c5000", "hex"), + //BITBOX.Script.opcodes.OP_1, + Buffer.from("01", "hex"), + Buffer.from(`SEND`), + Buffer.from(tokenId, "hex"), + Buffer.from(baseQtyHex, "hex") + ] + } + + return { script, outputs } + } catch (err) { + console.log(`Error in generateSendOpReturn()`) + throw err + } + } + + /** + * @api SLP.TokenType1.generateBurnOpReturn() generateBurnOpReturn() - OP_RETURN code for SLP Send tx + * @apiName generateBurnOpReturn + * @apiGroup SLP + * @apiDescription Generate the OP_RETURN value needed to create an SLP Send transaction that burns tokens. + * This is a slight variation of generateSendOpReturn(). It generates an SLP + * SEND transaction designed to burn a select quantity of tokens. + * + * It's assumed all elements in the tokenUtxos array belong to the same token. + * Returns an object with two properties: + * - script: an array of Bufers that is ready to fed into bchjs.Script.encode() to be turned into a transaction output. + * - outputs: an integer with a value of 1. There is no token change to be sent with this transaction. + */ + generateBurnOpReturn(tokenUtxos, sendQty) { try { const tokenId = tokenUtxos[0].tokenId const decimals = tokenUtxos[0].decimals diff --git a/test/unit/slp-tokentype1.js b/test/unit/slp-tokentype1.js index 9f9b6df..4943050 100644 --- a/test/unit/slp-tokentype1.js +++ b/test/unit/slp-tokentype1.js @@ -70,6 +70,41 @@ describe("#SLP TokenType1", () => { assert.hasAllKeys(result, ["script", "outputs"]) assert.isNumber(result.outputs) }) + + // it("should handle problematic configuration", async () => { + // // Mock UTXO. + // const tokenUtxos = [ + // { + // txid: + // "0bd6b874246202b4cbc2f501419a5ce6f9b01e8ba9521298afd15c7e8eac5951", + // vout: 2, + // value: "546", + // confirmations: 0, + // satoshis: 546, + // utxoType: "token", + // transactionType: "send", + // tokenId: + // "155784a206873c98acc09e8dabcccf6abf13c4c14d8662190534138a16bb93ce", + // tokenTicker: "PSF", + // tokenName: "PSF Testnet Token", + // tokenDocumentUrl: "", + // tokenDocumentHash: "", + // decimals: 8, + // tokenQty: 18004.71169917 + // } + // ] + // + // const result = await bchjs.SLP.TokenType1.generateSendOpReturn( + // tokenUtxos, + // 5000 + // ) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + // + // // console.log(`decoded: ${result.script[6].toString("ascii")}`) + // // const msg = Buffer.from(result.script[6], "hex").toString("ascii") + // const msg = result.script[6].toString("ascii") + // console.log(`msg: ${msg}`) + // }) }) describe("#generateGenesisOpReturn", () => {